2009-04-17 14 views
46

Sto usando Capistrano per eseguire un'attività remota. Il mio compito è simile al seguente:Capistrano & Bash: ignora il comando exit status

task :my_task do 
    run "my_command" 
end 

Il mio problema è che se my_command ha uno stato di uscita = 0, allora Capistrano considera fallito ed esce!. Come posso rendere capistrano andare avanti quando esci quando lo stato di uscita non è 0? Ho cambiato my_command a my_command;echo e funziona ma sembra un trucco.

risposta

75

Il modo più semplice è aggiungere semplicemente true alla fine del comando.

task :my_task do 
    run "my_command" 
    end 

Diventa

task :my_task do 
    run "my_command; true" 
    end 
+12

Non sono sicuro di cosa sia Capistano, ma ho trovato la mia strada qui a causa dello stesso problema con bash. E poi puoi usare "my_command || true" invece di "my_command; true" – Zitrax

5

È necessario applicare una patch al codice Capistrano se si desidera che funzioni diversamente con i codici di uscita; è hardcoded per generare un'eccezione se lo stato di uscita non è zero.

Ecco la parte pertinente di lib/capistrano/command.rb. La linea che inizia con if (failed ... è quella importante. Fondamentalmente dice che se ci sono valori di ritorno diversi da zero, genera un errore.

# 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

Immagino che questo sia solo per Capistrano 2, per Capistrano 3, è possibile utilizzare [risposta di Ciryon] (http: // StackOverflow.it/a/23424213/345959) – Smar

2

Ho appena reindirizzare STDERR e STDOUT a/dev/null, in modo che il

run "my_command" 

diventa

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

questo funziona per gli strumenti standard Unix piuttosto bene, in cui, per esempio, cp o ln potrebbe fallire, ma non si vuole fermare la distribuzione su un tale fallimento.

7

Il comando + grep + esce da zero in base a ciò che trova. Nel caso d'uso in cui vi preoccupate per l'uscita, ma non ti dispiace se è vuota, si scarta lo Stato di uscita in silenzio:

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

Normalmente, credo che la prima soluzione è proprio bene - mi piacerebbe rendilo documento tho:

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

trovo l'opzione più semplice per farlo:

run "my_command || :" 

Avviso: : è il comando NOP in modo che il codice di uscita viene semplicemente ignorato.

30

Per Capistrano 3, è possibile (come suggerito here) utilizzare il seguente:

execute "some_command.sh", raise_on_non_zero_exit: false 
+1

ha funzionato per me il meglio. – khelll

+0

opzione molto bella! – Aleksey

0

non ho sicuri sulla versione hanno aggiunto questo codice, ma mi piace la gestione di questo problema utilizzando 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 

Qui è dove questa caratteristica è implementata nella gemma. https://github.com/capistrano/sshkit/blob/4cfddde6a643520986ed0f66f21d1357e0cd458b/lib/sshkit/command.rb#L94

Problemi correlati