50

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

task :my_task do
  run "my_command"
end

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

4

7 回答 7

79

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

  task :my_task do
    run "my_command"
  end

变成

  task :my_task do
    run "my_command; true"
  end
于 2009-08-25T14:19:53.920 回答
40

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

execute "some_command.sh", raise_on_non_zero_exit: false
于 2014-05-02T08:49:46.957 回答
6

+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."'}
于 2009-04-21T19:09:42.503 回答
5

如果您希望 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
于 2009-04-17T04:57:43.273 回答
5

我找到了最简单的选择:

run "my_command || :"

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

于 2012-07-11T08:17:13.653 回答
2

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

run "my_command"

变成

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

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

于 2009-04-17T05:17:27.530 回答
0

我不确定他们添加了这个代码是什么版本,但我喜欢通过使用来处理这个问题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

Here is where that feature is implemented in the gem. https://github.com/capistrano/sshkit/blob/4cfddde6a643520986ed0f66f21d1357e0cd458b/lib/sshkit/command.rb#L94

于 2017-08-21T23:58:53.103 回答