Capistrano & Bash: ignore command exit status

前端 未结 7 581
礼貌的吻别
礼貌的吻别 2021-01-31 14:11

I\'m using Capistrano run a remote task. My task looks like this:

task :my_task do
  run \"my_command\"
end

My problem is that if my_comm

相关标签:
7条回答
  • 2021-01-31 14:44

    The simplest way is to just append true to the end of your command.

      task :my_task do
        run "my_command"
      end
    

    Becomes

      task :my_task do
        run "my_command; true"
      end
    
    0 讨论(0)
  • 2021-01-31 14:46

    I not sure what version they added this code but I like handling this problem by using 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/4cfffffde6a643520986ed0f66f21d1357e0cd458b/lib/sshkit/command.rb#L94

    0 讨论(0)
  • 2021-01-31 14:49

    I find the easiest option to do this:

    run "my_command || :"
    

    Notice: : is the NOP command so the exit code will simply be ignored.

    0 讨论(0)
  • 2021-01-31 14:53

    The +grep+ command exits non-zero based on what it finds. In the use case where you care about the output but don't mind if it's empty, you'll discard the exit state silently:

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

    Normally, I think the first solution is just fine -- I'd make it document itself tho:

    cmd = "my_command with_args escaped_correctly"
    run %Q{bash -c '#{cmd} || echo "Failed: [#{cmd}] -- ignoring."'}
    
    0 讨论(0)
  • 2021-01-31 14:55

    You'll need to patch the Capistrano code if you want it to do different things with the exit codes; it's hard-coded to raise an exception if the exit status is not zero.

    Here's the relevant portion of lib/capistrano/command.rb. The line that starts with if (failed... is the important one. Basically it says if there are any nonzero return values, raise an error.

    # 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
    
    0 讨论(0)
  • 2021-01-31 14:57

    I just redirect STDERR and STDOUT to /dev/null, so your

    run "my_command"
    

    becomes

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

    this works for standard unix tools pretty well, where, say, cp or ln could fail, but you don't want to halt deployment on such a failure.

    0 讨论(0)
提交回复
热议问题