【问题标题】:How can you check to see if a file exists (on the remote server) in Capistrano?如何检查 Capistrano 中是否存在文件(在远程服务器上)?
【发布时间】:2010-12-12 07:21:36
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: ruby file capistrano exists


    【解决方案1】:

    在 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 命令。

    【讨论】:

    • 非常感谢!我最终得到了类似unless test("[ -f " + shared_path.to_s + "/a_shared_file.txt ]" )
    • Matt,你能链接到test 的文档吗?这是一个很难搜索的词。谢谢!
    • 请注意,在上下文中在这里不起作用,因此您需要使用绝对路径进行测试。如果您想检查目录是否存在,请使用[ -p ... ]
    【解决方案2】:

    @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 -- 查看options you can pass 以获得更多控制。

    【讨论】:

    • 每个人,请给这个答案投反对票,对高票投反对票,stackoverflow 不可能有这么大的错误!
    • 如果你有超过目标,你的最终条件不会失败吗?结果数组可以是 [true, true, true]。我想你想使用“results.all”?而是。
    • @TeflonTed -- 是的,你是对的。我更新了答案以反映这一变化。谢谢!
    • 在我看来,在else 案例中,您应该使用echo -n 'false';...
    • 我同意@RichardCook,没有 else 分支,结果为空,[].all? 为假。在我的系统上,你只输入它输出的东西的 invoke_command 块。
    【解决方案3】:

    受@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
    

    【讨论】:

    • 人! capture() 函数只从第一台服务器检索数据,所以请不要以此为基础! capistrano 是多服务器
    • @knocte -- 感谢您指出这一点,我能够提出一个适用于所有匹配服务器的解决方案。请参阅下面的答案。
    • 酷!每个人都请否决这个回应并支持帕特里克的!这是一个彻底的失败
    【解决方案4】:

    可能你想做的是:

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

    【讨论】:

    • 谢谢。我假设您的意思是用“捕获”方法包装它? capify.org/index.php/Capture
    • 在 ruby​​ 中有另一种方法来捕获输出:使用反引号:isFileExist = ` if [ -d #{dir_path} ];然后回显“是”;否则回显“否”; fi `.strip(确保删除反引号内的多余空格:我已添加它们以帮助 SO 显示)
    【解决方案5】:

    在 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
    

    【讨论】:

      猜你喜欢
      • 2012-06-13
      • 1970-01-01
      • 2014-01-31
      • 2014-12-07
      • 2013-01-01
      • 2011-06-03
      • 1970-01-01
      • 2011-01-25
      • 1970-01-01
      相关资源
      最近更新 更多