43

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

我发现了一个使用 shell hack 的结果,例如:

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

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

有人优雅地解决了这个问题吗?

4

5 回答 5

61

在 capistrano 3 中,您可以执行以下操作:

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

这很好,因为它将远程测试的结果返回给您的本地 ruby​​ 程序,您可以使用更简单的 shell 命令工作。

于 2014-01-02T04:28:50.020 回答
49

@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- 查看您可以传递的选项以获得更多控制权。

于 2013-03-15T15:28:07.620 回答
21

受@bhups 响应的启发,通过测试:

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
于 2009-11-02T15:36:01.190 回答
5

可能你想做的是:

isFileExist = 'if [ -d #{dir_path} ]; then echo "yes"; else echo "no"; fi'.strip
puts "File exist" if isFileExist == "yes"
于 2009-11-02T14:36:59.070 回答
4

在 capistrano 中使用 run 命令(在远程服务器上执行 shell 命令)之前,我已经这样做了

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

  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
于 2009-11-02T22:20:50.663 回答