2013-09-10 7 views
74

Ich habe eine Reihe von Systemaufrufen in Ruby wie folgt und ich möchte ihre Exit-Codes gleichzeitig überprüfen, so dass mein Skript beendet, wenn dieser Befehl fehlschlägt.ruby ​​system command prüfen exit code

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

Ich mag so etwas wie

system("VBoxManage createvm --name test1", 0) < - wo der zweite Parameter den Exit-Code überprüft und bestätigt, dass das Systemaufruf erfolgreich war, und wenn nicht, wird es einen Fehler erhöhen oder etwas von diese Sorte.

Ist das überhaupt möglich?

Ich habe versucht, etwas in die Richtung dieser und das hat auch nicht funktioniert.

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

oder

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

möglich Duplikat [Beschäftigten Befehlszeilenfehler mit% x] (http://stackoverflow.com/questions/4771930/catching-command-line-errors-using-x) –

+0

In dem obigen Beispiel: 'exit_code' ist eine Zeichenkette - entweder' "0 \ n" 'oder' "1 \ n" ', so dass 'exit_code! = 0' immer wahr ist – dgmstuart

Antwort

129

Vom documentation:

System kehrt true, wenn der Befehl gibt Null Exit-Status, false für nicht Null Exit-Status. Gibt nil zurück, wenn die Ausführung des Befehls fehlschlägt.

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

Außerdem

Ein Fehlerstatus ist in $? verfügbar.

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

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

und wie es die Ausgabe (nicht Exit-Code) zu einer Variablen erfassen? –

+2

@ Alexander-Supertramp siehe http://StackOverflow.com/Q/690151/477037 – Stefan

+0

Wenn Sie in einer Rails-Konsole sind, Testen Sie dies, nur daran denken, Sie können den Wert von $ verlieren? Sie müssen es also als Teil Ihres REPL-Befehls erfassen. '[10] pry (main)> system (" touch/root/test2>/dev/null ") => false [11] pry (main)> $ ?. exitstatus => 0 [12] pry (main)> system ("touch/root/test 2>/dev/null"); $ exitstatus => 1' – lardcanoe

21

systemfalse kehrt, wenn der Befehl einen Nicht-Null-Exit-Code hat, oder nil wenn kein Befehl ist.

Deshalb

system("foo") or exit 

oder

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

funktionieren sollte, und sind recht präzise.

5

Sie sind nicht das Ergebnis Ihrer system Anruf erfassen, die in dem das Ergebnis Code zurückgegeben:

exit_code = system("ruby test.rb") 

jedes system Anruf oder eine gleichwertige Denken Sie daran, die die Graviszeichen-Verfahren umfasst, laicht eine neue Shell Daher ist es nicht möglich, das Ergebnis der vorherigen Shell-Umgebung zu erfassen. In diesem Fall exit_code ist true, wenn alles funktioniert, sonst nil.

Der Befehl popen3 bietet mehr Low-Level-Details.

+2

[' Open3.capture3'] (http://www.ruby-doc.org/stdlib-2.0.0/libdoc/open3/rdoc/Open3.html#method-c-capture3) ist eine besonders einfache Methode für diese Art von Aufgabe. –

+2

exit_code ist wahrscheinlich nicht der beste Name dafür – drewish

3

Eine Möglichkeit, dies zu Kette zu tun ist, sie and oder && mit:

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

Der zweite Anruf wird nicht ausgeführt werden, wenn die erste ausfällt.

Sie können die in einem if() wickeln Sie einige Flusskontrolle zu geben:

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

Für mich ich lieber `` die Shell-Befehle verwenden rufen und $ überprüfen? um den Prozessstatus zu erhalten. Der $? Ist ein Prozessstatusobjekt, können Sie die Prozessinformationen des Befehls von diesem Objekt abrufen, einschließlich Statuscode, Ausführungsstatus, PID usw.

Einige nützliche Methoden des $? Objekt:

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