2013-09-10 9 views
74

Ho un sacco di chiamate di sistema in ruby ​​come il seguente e voglio controllare i loro codici di uscita simultaneamente in modo che il mio script esca se quel comando fallisce.comando di sistema ruby ​​controllare il codice di uscita

system("VBoxManage createvm --name test1") 
system("ruby test.rb") 

voglio qualcosa di simile

system("VBoxManage createvm --name test1", 0) < - in cui il secondo parametro controlla il codice di uscita e conferma che quella chiamata di sistema ha avuto successo, e se non, sarà genera un errore o di fare qualcosa di quel genere.

È possibile?

Ho provato qualcosa del genere e anche questo non ha funzionato.

system("ruby test.rb") 
system("echo $?") 

o

`ruby test.rb` 
exit_code = `echo $?` 
if exit_code != 0 
    raise 'Exit code is not zero' 
end 
+2

possibile duplicato [errori Facendo riga di comando utilizzando% x] (http://stackoverflow.com/questions/4771930/catching-command-line-errors-using-x) –

+0

In precedenza Ad esempio, 'exit_code' sarà una stringa - o" "0 \ n" 'o' "1 \ n" ', quindi' exit_code! = 0' sarà sempre true – dgmstuart

risposta

129

Dal documentation:

sistema restituisce true se il comando fornisce lo stato di zero uscita, false per stato non di uscita zero. Restituisce nil se l'esecuzione del comando non riesce.

system("unknown command")  #=> nil 
system("echo foo")   #=> true 
system("echo foo | grep bar") #=> false 

Inoltre

uno stato di errore è disponibile in $?.

system("VBoxManage createvm --invalid-option") 

$?    #=> #<Process::Status: pid 9926 exit 2> 
$?.exitstatus #=> 2 
+1

e come acquisire l'output (non il codice di uscita) su una variabile? –

+2

@ alexander-supertramp, vedi http://stackoverflow.com/q/690151/477037 – Stefan

+0

Se ti trovi in ​​una console di rotaie, verificala, tieni presente che potresti perdere il valore di $? quindi è necessario catturarlo come parte del comando REPL '[10] pry (principale)> sistema (" touch/root/test 2>/dev/null ") => false [11] pry (main)> $?. exitstatus => 0 [12] pry (principale)> sistema ("touch/root/test 2>/dev/null"); $ ?. exitstatus => 1' – lardcanoe

21

system rendimenti false se il comando ha un codice di uscita diverso da zero, o nil se non v'è alcun comando.

Pertanto

system("foo") or exit 

o

system("foo") or raise "Something went wrong with foo" 

dovrebbe funzionare, e sono ragionevolmente concisa.

5

Non stai catturando il risultato della vostra system chiamata, che è dove il codice risultato viene restituito:

exit_code = system("ruby test.rb") 

Ricordati di ogni system chiamata o equivalente, che include il backtick-metodo, genera un nuovo shell , quindi non è possibile catturare il risultato di un ambiente precedente della shell. In questo caso exit_code è true se tutto ha funzionato, nil in caso contrario.

Il comando popen3 fornisce ulteriori dettagli di basso livello.

+2

['Open3.capture3'] (http://www.ruby-doc.org/stdlib-2.0.0/libdoc/open3/rdoc/Open3.html#method-c-capture3) è un metodo particolarmente facile da utilizzare per questo tipo di attività. –

+2

exit_code probabilmente non è il nome migliore per questo – drewish

3

Un modo per farlo è quello di catena utilizzando and o &&:

system("VBoxManage createvm --name test1") and system("ruby test.rb") 

La seconda chiamata non viene eseguito se la prima fallisce.

Puoi avvolgere quelli in un if() per darvi qualche controllo di flusso:

if (
    system("VBoxManage createvm --name test1") && 
    system("ruby test.rb") 
) 
    # do something 
else 
    # do something with $? 
end 
15

Per quanto mi riguarda, ho preferito utilizzare `` per chiamare i comandi di shell e controllare $? per ottenere lo stato del processo. $? è un oggetto stato del processo, è possibile ottenere le informazioni di processo del comando da questo oggetto, tra cui: codice di stato, stato di esecuzione, pid, ecc.

Alcuni metodi utili del $? oggetto:

$?.exitstatus => return error code  
    $?.success? => return true if error code is 0, otherwise false 
    $?.pid => created process pid