【问题标题】:Capistrano & Bash: ignore command exit statusCapistrano & Bash:忽略命令退出状态
【发布时间】:2010-10-20 00:22:35
【问题描述】:

我正在使用 Capistrano 运行远程任务。我的任务如下所示:

task :my_task do
  run "my_command"
end

我的问题是,如果my_command 的退出状态为 != 0,则 Capistrano 认为它失败并退出。当退出状态不是 0 时,如何让 capistrano 继续运行?我已将 my_command 更改为 my_command;echo 并且它可以工作,但感觉就像一个 hack。

【问题讨论】:

    标签: ruby-on-rails ruby bash capistrano


    【解决方案1】:

    最简单的方法是在命令末尾附加 true。

      task :my_task do
        run "my_command"
      end
    

    变成

      task :my_task do
        run "my_command; true"
      end
    

    【讨论】:

    • 不确定 capistano 是什么,但由于 bash 存在同样的问题,我在这里找到了方法。然后你可以使用“my_command || true”而不是“my_command; true”
    【解决方案2】:

    对于 Capistrano 3,您可以(如建议 here)使用以下内容:

    execute "some_command.sh", raise_on_non_zero_exit: false
    

    【讨论】:

    • 非常好的选择!
    【解决方案3】:

    +grep+ 命令根据它找到的内容以非零值退出。在您关心输出但不介意它是否为空的用例中,您将默默地丢弃退出状态:

    run %Q{bash -c 'grep #{escaped_grep_command_args} ; true' }
    

    通常,我认为第一个解决方案很好——我会让它自己记录:

    cmd = "my_command with_args escaped_correctly"
    run %Q{bash -c '#{cmd} || echo "Failed: [#{cmd}] -- ignoring."'}
    

    【讨论】:

      【解决方案4】:

      如果您希望 Capistrano 代码对退出代码执行不同的操作,则需要修补它;如果退出状态不为零,则通过硬编码引发异常。

      这是 lib/capistrano/command.rb 的相关部分。以if (failed... 开头的那一行是重要的。基本上它说如果有任何非零返回值,就会引发错误。

      # Processes the command in parallel on all specified hosts. If the command
      # fails (non-zero return code) on any of the hosts, this will raise a
      # Capistrano::CommandError.
      def process!
        loop do
          break unless process_iteration { @channels.any? { |ch| !ch[:closed] } }
        end
      
        logger.trace "command finished" if logger
      
        if (failed = @channels.select { |ch| ch[:status] != 0 }).any?
          commands = failed.inject({}) { |map, ch| (map[ch[:command]] ||= []) << ch[:server]; map }
          message = commands.map { |command, list| "#{command.inspect} on #{list.join(',')}" }.join("; ")
          error = CommandError.new("failed: #{message}")
          error.hosts = commands.values.flatten
          raise error
        end
      
        self
      end
      

      【讨论】:

      • 我猜这只适用于 Capistrano 2,对于 Capistrano 3,你可以使用Ciryon’s answer
      【解决方案5】:

      我找到了最简单的方法:

      run "my_command || :"
      

      注意:: 是 NOP 命令,因此退出代码将被简单地忽略。

      【讨论】:

        【解决方案6】:

        我只是将 STDERR 和 STDOUT 重定向到 /dev/null,所以你的

        run "my_command"
        

        变成

        run "my_command > /dev/null 2> /dev/null"
        

        这非常适用于标准 unix 工具,例如 cp 或 ln 可能会失败,但您不想在此类失败时停止部署。

        【讨论】:

          【解决方案7】:

          我不确定他们添加此代码的版本,但我喜欢使用 raise_on_non_zero_exit 处理此问题

          namespace :invoke do
            task :cleanup_workspace do
              on release_roles(:app), in: :parallel do
                execute 'sudo /etc/cron.daily/cleanup_workspace', raise_on_non_zero_exit: false
              end
            end
          end
          

          这里是该功能在 gem 中实现的地方。 https://github.com/capistrano/sshkit/blob/4cfddde6a643520986ed0f66f21d1357e0cd458b/lib/sshkit/command.rb#L94

          【讨论】:

            猜你喜欢
            • 2013-02-10
            • 1970-01-01
            • 1970-01-01
            • 2011-07-08
            • 2014-03-25
            • 1970-01-01
            • 1970-01-01
            • 2013-02-28
            • 2014-12-03
            相关资源
            最近更新 更多