Ruby System Befehl Check Exit Code


106

Ich habe eine Reihe von Systemaufrufen in Ruby wie die folgenden und möchte deren Exit-Codes gleichzeitig überprüfen, damit mein Skript beendet wird, wenn dieser Befehl fehlschlägt.

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

Ich möchte so etwas wie

system("VBoxManage createvm --name test1", 0) <- wobei der zweite Parameter den Exit-Code überprüft und bestätigt, dass dieser Systemaufruf erfolgreich war, und wenn nicht, wird ein Fehler ausgelöst oder etwas in dieser Art ausgeführt.

Ist das überhaupt möglich?

Ich habe etwas in dieser Richtung versucht 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


Im obigen Beispiel exit_codewird eine Zeichenfolge sein - entweder "0\n"oder "1\n", so exit_code != 0wird es immer wahr sein
dgmstuart

Antworten:


166

Aus der Dokumentation :

Das System gibt zurück, truewenn der Befehl den Status "Null beenden" für den Status " falseNicht beenden" zurückgibt . Gibt zurück, nilwenn die Befehlsausführung 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

2
und wie erfasst man die Ausgabe (nicht den Exit-Code) einer Variablen?
レ ッ ク ス

Wenn Sie sich in einer Rails-Konsole befinden und dies testen, denken Sie daran, dass Sie möglicherweise den Wert von $ verlieren. Sie müssen es also als Teil Ihres REPL-Befehls [10] pry(main)> system("touch /root/test 2> /dev/null") => false [11] pry(main)> $?.exitstatus => 0 [12] pry(main)> system("touch /root/test 2> /dev/null"); $?.exitstatus => 1
erfassen

Ein weiterer hervorragender Vergleich von systemBackticks %xund execwird hier bereitgestellt: stackoverflow.com/questions/6338908/…
Tom Harrison

38

Für mich zog ich es vor, `` zu verwenden, um die Shell-Befehle aufzurufen und $? um den Prozessstatus zu erhalten. Die $? 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

1
Mit Hilfe von Rubocop, fand ich heraus , dass der lesbare Alias für $?ist$CHILD_STATUS
RajaRaviVarma

26

systemGibt zurück, falsewenn der Befehl einen Exit-Code ungleich Null hat oder nilwenn kein Befehl vorhanden ist.

Deshalb

system( "foo" ) or exit

oder

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

sollte funktionieren und sind einigermaßen prägnant.


6

Sie erfassen nicht das Ergebnis Ihres systemAnrufs. Hier wird der Ergebniscode zurückgegeben:

exit_code = system("ruby test.rb")

Denken Sie daran, dass bei jedem systemAufruf oder Äquivalent, zu dem auch die Backtick-Methode gehört, eine neue Shell erzeugt wird, sodass das Ergebnis der Umgebung einer vorherigen Shell nicht erfasst werden kann. In diesem Fall exit_codeist, truewenn alles geklappt hat, nilsonst.

Der popen3Befehl bietet mehr Details auf niedriger Ebene.


2
Open3.capture3ist eine besonders einfache Methode für diese Art von Aufgabe.
der Blechmann

6

Eine Möglichkeit, dies zu tun, besteht darin, sie mit andoder zu verketten &&:

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

Der zweite Aufruf wird nicht ausgeführt, wenn der erste fehlschlägt.

Sie können diese in eine einwickeln if (), um eine gewisse Flusskontrolle zu erhalten:

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

Dies ist bisher das, was ich erreichen möchte, unkompliziert und klar genug. Vielen Dank
Mochadwi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.