如何检查在Capistrano中是否存在文件(在远程服务器上)?

像我在Googleverse看到的许多其他人一样,我成为File.exists?受害者File.exists? 陷阱,这当然会检查您的本地文件系统,而不是您正在部署的服务器。

我发现一个结果使用了一个shell黑客:

 if [[ -d #{shared_path}/images ]]; then ... 

但是这并不适合我,除非它很好地包裹在Ruby方法中。

有谁有解决这个优雅?

@knocte是正确的, capture是有问题的,因为通常每个人都将目标部署到多个主机(并且捕获只获取来自第一个主机的输出)。 为了检查所有主机,您需要使用invoke_command (这是capture内部使用的)。 下面是一个例子,我检查确保所有匹配的服务器上存在一个文件:

 def remote_file_exists?(path) results = [] invoke_command("if [ -e '#{path}' ]; then echo -n 'true'; fi") do |ch, stream, out| results << (out == 'true') end results.all? end 

请注意, invoke_command默认使用run – 检查您可以传递更多的控制选项 。

在capistrano 3,你可以这样做:

 on roles(:all) do if test("[ -f /path/to/my/file ]") # the file exists else # the file does not exist end end 

这很好,因为它将远程testing的结果返回到本地ruby程序,并且可以使用更简单的shell命令。

受@bhups响应启发,testing:

 def remote_file_exists?(full_path) 'true' == capture("if [ -e #{full_path} ]; then echo 'true'; fi").strip end namespace :remote do namespace :file do desc "test existence of missing file" task :missing do if remote_file_exists?('/dev/mull') raise "It's there!?" end end desc "test existence of present file" task :exists do unless remote_file_exists?('/dev/null') raise "It's missing!?" end end end end 

可能你想做的是:

 isFileExist = 'if [ -d #{dir_path} ]; then echo "yes"; else echo "no"; fi'.strip puts "File exist" if isFileExist == "yes" 

我在capistrano中使用run命令(在远程服务器上执行shell命令)

例如,这里有一个capistrano任务,它将检查shared / configs目录中是否存在database.yml,如果存在则将其链接。

  desc "link shared database.yml" task :link_shared_database_config do run "test -f #{shared_path}/configs/database.yml && ln -sf #{shared_path}/configs/database.yml #{current_path}/config/database.yml || echo 'no database.yml in shared/configs'" end