8
votes

Soulever une exception sur l'échec de la commande shell?

J'écris des scripts en rubis et je dois interfacer avec du code non rubis via des commandes shell. Je sais qu'il y a au moins 6 différentes manières d'exécution des commandes shell Depuis de rubis, malheureusement, aucun de ceux-ci ne semble arrêter l'exécution lorsqu'une commande shell échoue.

Fondamentalement, je cherche quelque chose qui fait l'équivalent de: xxx

... dans un script Bash. Idéalement, la solution susciterait une exception lorsque la commande échoue (c'est-à-dire en vérifiant une valeur de retour non nulle), peut-être avec STDERR comme message. Ce ne serait pas trop difficile à écrire, mais cela semble que cela devrait exister déjà. Y a-t-il une option que je ne trouve tout simplement pas?


0 commentaires

4 Réponses :


9
votes

Vous pouvez utiliser l'une des variables spéciales de Ruby. Le $? (analogue au même script shell var).

`ls`
if $?.to_s == "0"
  # Ok to go
else
  # Not ok
end


8 commentaires

Pourquoi utiliseriez-vous to_s pour comparer avec la chaîne 0 ? si $? == 0


Je dirais même si $ ?. zéro?


@Nakilon $ ?. zéro? Soulevez le nométhodeurror


@ Mu-Ikjeon, vous ferez face à cela si vous n'avez pas encore appelé de sous-processus, car $? est nil depuis le début.


@Nakilon $? est le processus :: classe de statut. Met $ ?. Processus de classe :: Statut La classe n'a pas de zéro? ' méthode. ruby-doc.org/core-2.2.0/process/status. HTML


@ Mu-ikjeon, oh tu as raison, bizarre. On dirait que le code d'erreur est dans $ ?. exitStatus Stackoverflow.com/a/38683399/322020


La meilleure façon de vérifier est si $ ?. Succès? ruby-doc.org/core-2.2.0/process/status.html#method-i-success -3f . La façon dont je l'utilise est quitte $ ?. to_i à moins que $ $ ?. Succès?


$ ?. to_s retourne "PID 908 sortie 0" lorsque je l'exécute avec système ("Commande"), cela ne fonctionne donc pas. Cependant, système ("commandement") et également $ ?. Succès? Les deux rendent vrai ou faux selon qu'il y avait une erreur.



9
votes

La manière la plus simple serait de créer une nouvelle fonction (ou de redéfinir un fichier existant) pour appeler le système () et de vérifier le code d'erreur.

quelque chose comme: p>

old_sys = system

def system(...)
  old_system(...)
  if $? != 0 then raise :some_exception
end


3 commentaires

Ouais, c'était ce que je pensais quand j'ai dit "ne serait pas trop difficile d'écrire", mais cela semble-t-il déjà quelque chose qui aurait dû être résolu déjà, vous savez? Merci pour l'exemple.


Bien que, vous souhaiteriez augmenter au lieu de lancer


FYI: L'alias lisible pour $? est $ enfant_status . Refs: docs.ruby-lang.org/fr/2.2. 0 / processus / status.html , ruby-doc.org/stdlib-2.5.0/libdoc/english/rdoc/english.html



8
votes

minuscule un peu plus simple: vous n'avez pas besoin de vérifier $? w / système , et puisque la commande que vous avez exécutée sera sortie sur starr vous pouvez généralement juste juste une sortie non nulle plutôt que d'élever une exception avec une trace de pile laide: xxx

afin que vous puissiez prendre une étape plus loin et faire: xxx

... qui serait court-circuit et échoué sur une erreur (en plus d'être difficile à lire).

ref: de ruby ​​2.0 doc pour système (bien que vrai de 1.8.7 aussi):

System renvoie true si la commande donne un état de sortie zéro, false pour statut de sortie non nul.

http: // www.ruby-doc.org/core-2.0.0/kernel.html#method-i-i-i-i-System


1 commentaires

Intéressant, j'aime ça. Pourriez-vous ajouter un lien à votre référence (la partie des documents rubis où vous l'avez trouvée)?



10
votes

Ruby 2.6 ajoute un Exception: code > Argument :

system('ctat nonexistent.txt', exception: true) # Errno::ENOENT (No such file or directory - ctat)


0 commentaires