code de sortie de contrôle de commande système ruby


106

J'ai un tas d'appels système dans ruby ​​tels que les suivants et je veux vérifier leurs codes de sortie simultanément afin que mon script se termine si cette commande échoue.

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

Je veux quelque chose comme

system("VBoxManage createvm --name test1", 0) <- où le deuxième paramètre vérifie le code de sortie et confirme que cet appel système a réussi, et sinon, il déclenchera une erreur ou fera quelque chose de ce genre.

Est-ce possible du tout?

J'ai essayé quelque chose du genre et cela n'a pas fonctionné non plus.

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

ou

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


Dans l'exemple ci-dessus, exit_codesera une chaîne - soit "0\n"ou "1\n", donc exit_code != 0sera toujours vrai
dgmstuart

Réponses:


166

De la documentation :

le système renvoie truesi la commande donne un statut de sortie nul, falsepour un statut de sortie différent de zéro. Renvoie nilsi l'exécution de la commande échoue.

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

en outre

Un état d'erreur est disponible dans $?.

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

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

2
et comment capturer sa sortie (pas le code de sortie) dans une variable?
ア レ ッ ク ス

Si vous êtes dans une console de rails et que vous testez cela, gardez à l'esprit que vous risquez de perdre la valeur de $? vous devez donc le capturer dans le cadre de votre commande REPL [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
lardcanoe

Une autre excellente comparaison de system, backticks, %xet execfournie ici: stackoverflow.com/questions/6338908/…
Tom Harrison

38

Pour moi, j'ai préféré utiliser `` pour appeler les commandes shell et vérifier $? pour obtenir le statut du processus. Le $? est un objet d'état de processus, vous pouvez obtenir les informations de processus de la commande à partir de cet objet, y compris: code d'état, état d'exécution, pid, etc.

Quelques méthodes utiles du $? objet:

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

1
Avec l'aide de Rubocop, j'ai découvert que l'alias lisible pour $?est$CHILD_STATUS
RajaRaviVarma

26

systemrenvoie falsesi la commande a un code de sortie différent de zéro, ou nils'il n'y a pas de commande.

Par conséquent

system( "foo" ) or exit

ou

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

devraient fonctionner et sont raisonnablement concis.


6

Vous ne capturez pas le résultat de votre systemappel, c'est là que le code de résultat est renvoyé:

exit_code = system("ruby test.rb")

Souvenez-vous que chaque systemappel ou équivalent, qui inclut la méthode backtick, génère un nouveau shell, il n'est donc pas possible de capturer le résultat de l'environnement d'un shell précédent. Dans ce cas , exit_codeest truesi tout a fonctionné, nilautrement.

La popen3commande fournit plus de détails de bas niveau.


2
Open3.capture3est une méthode particulièrement simple à utiliser pour ce type de tâche.
the Tin Man

6

Une façon de le faire est de les chaîner en utilisant andou &&:

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

Le deuxième appel ne sera pas exécuté si le premier échoue.

Vous pouvez les envelopper dans un if ()pour vous donner un contrôle de flux:

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

C'est jusqu'ici ce que je veux réaliser, assez simple et clair. Merci
mochadwi
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.