Capistrano & Bash: игнорировать статус команды выхода - PullRequest
48 голосов
/ 17 апреля 2009

Я использую Capistrano для запуска удаленной задачи. Моя задача выглядит так:

task :my_task do
  run "my_command"
end

Моя проблема в том, что если my_command имеет статус выхода! = 0, то Capistrano считает, что это не удалось, и завершает работу. Как я могу заставить capistrano продолжать работу при выходе, если статус выхода не равен 0? Я изменил my_command на my_command;echo, и это работает, но похоже на взлом.

Ответы [ 7 ]

76 голосов
/ 25 августа 2009

Самый простой способ - просто добавить true в конец вашей команды.

  task :my_task do
    run "my_command"
  end

Становится

  task :my_task do
    run "my_command; true"
  end
35 голосов
/ 02 мая 2014

Для Capistrano 3 вы можете (как предлагается здесь ) использовать следующее:

execute "some_command.sh", raise_on_non_zero_exit: false
6 голосов
/ 21 апреля 2009

Команда + 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."'}
5 голосов
/ 17 апреля 2009

Вам нужно будет исправить код 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
4 голосов
/ 11 июля 2012

Я считаю, что проще всего сделать это:

run "my_command || :"

Примечание: : - команда NOP, поэтому код выхода будет просто проигнорирован.

2 голосов
/ 17 апреля 2009

Я просто перенаправляю STDERR и STDOUT в / dev / null, поэтому ваш

run "my_command"

становится

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

это хорошо работает для стандартных инструментов Unix, где, скажем, cp или ln могут дать сбой, но вы не хотите останавливать развертывание при таком сбое.

0 голосов
/ 22 августа 2017

Я не уверен, в какой версии они добавили этот код, но мне нравится решать эту проблему с помощью 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

Вот где эта функция реализована в геме. https://github.com/capistrano/sshkit/blob/4cfddde6a643520986ed0f66f21d1357e0cd458b/lib/sshkit/command.rb#L94

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...