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.
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
Pour Capistrano 3, vous pouvez (comme suggéré ici ) utiliser les éléments suivants:
execute "some_command.sh", raise_on_non_zero_exit: false
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."'}
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
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é.
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.
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