web-dev-qa-db-fra.com

Capistrano & Bash: ignorer le statut de sortie de la commande

J'utilise Capistrano exécuter une tâche à distance. Ma tâche ressemble à ceci:

task :my_task do
  run "my_command"
end

Mon problème est que si my_command a un statut de sortie! = 0, Capistrano considère que cela a échoué et se ferme. Comment puis-je faire en sorte que capistrano continue à fonctionner lors de la sortie lorsque le statut de sortie n'est pas 0? J'ai changé my_command en my_command;echo et cela fonctionne, mais cela ressemble à un hack.

48
nicholaides

La méthode la plus simple consiste à ajouter true à la fin de votre commande.

  task :my_task do
    run "my_command"
  end

Devient

  task :my_task do
    run "my_command; true"
  end
76
mthorley

Pour Capistrano 3, vous pouvez (comme suggéré ici ) utiliser les éléments suivants: 

execute "some_command.sh", raise_on_non_zero_exit: false
34
Ciryon

La commande + grep + quitte non-zéro en fonction de ce qu'elle trouve. Dans le cas d'utilisation où vous vous souciez de la sortie mais ne vous inquiétez pas si elle est vide, vous écarterez l'état de sortie en silence:

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

Normalement, je pense que la première solution est très bien - je le ferais documenter lui-même que:

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

Vous devrez patcher le code Capistrano si vous voulez que les codes de sortie fassent des choses différentes. il est codé en dur pour générer une exception si le statut de sortie n'est pas nul.

Voici la partie pertinente de lib/capistrano/command.rb. La ligne qui commence par if (failed... est la plus importante. En gros, si une valeur de retour différente de zéro est définie, une erreur est générée.

# 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
5
Sarah Mei

Je trouve l'option la plus simple pour faire ceci:

run "my_command || :"

Remarque: : étant la commande NOP, le code de sortie sera simplement ignoré.

4
Besi

Je viens de rediriger STDERR et STDOUT vers/dev/null, donc votre

run "my_command"

devient

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

cela fonctionne assez bien pour les outils unix standard, où, par exemple, cp ou ln pourraient échouer, mais vous ne voulez pas arrêter le déploiement en cas d'échec.

2
Terry

Je ne sais pas quelle version ils ont ajouté ce code mais j'aime gérer ce problème en utilisant 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

Voici où cette fonctionnalité est implémentée dans la gemme. https://github.com/capistrano/sshkit/blob/4cfddde6a643520986ed0f66f21d1357e0cd458b/lib/sshkit/command.rb#L94

0
Brandt