J'écris un script shell et je dois vérifier qu'une application de terminal a été installée. Je veux utiliser une commande TRY / CATCH pour ce faire, sauf s'il existe une manière plus nette.
bash
shell
error-handling
Lee Probert
la source
la source
help test
pourrait vous aider à trouver la solution à votre problème.trap
commande.Réponses:
Non.
Bash n'a pas autant de luxe que l'on peut en trouver dans de nombreux langages de programmation.
Il n'y a pas
try/catch
de bash; cependant, on peut obtenir un comportement similaire en utilisant&&
ou||
.En utilisant
||
:si
command1
échoue alorscommand2
s'exécute comme suitDe même, l'utilisation de
&&
,command2
s'exécutera en cas decommand1
succèsL'approximation la plus proche de
try/catch
est la suivanteBash contient également des mécanismes de gestion des erreurs
il arrête votre script si une commande simple échoue.
Et pourquoi pas
if...else
. C'est votre meilleur ami.la source
#save your output
n'échoue pas, sinon le bloc "catch" s'exécutera toujours.if...else
construction. Cela implique-t-il que les commandes bash se résolvent comme "véridiques" si elles s'exécutent correctement et "fausses" si elles échouent?set -e
n'est pas nécessairement la meilleure façon de faire les choses; voici quelques contre-arguments / cas particuliers: mywiki.wooledge.org/BashFAQ/105Sur la base de quelques réponses que j'ai trouvées ici, je me suis fait un petit fichier d'aide à la source pour mes projets:
trycatch.sh
voici un exemple à quoi il ressemble en cours d'utilisation:
la source
||
aprèscatch
et avant le{}
bloc? J'aurais pensé que c'était un&&
if False or run_if_failed()
signifie que le court-circuit OU a essayé la première instruction qui n'est pas retournée vraie et passe maintenant à l'instruction suivante.&&
ne fonctionnerait pas car la première instruction (try
) a produit false, ce qui signifie que l'catch
instruction n'est pas nécessaire par la règle de tautologiefalse&any equals false
. Seul un court-circuit non ET ET / OU exécuterait les deux.J'ai développé une implémentation try & catch presque parfaite dans bash, qui vous permet d'écrire du code comme:
Vous pouvez même imbriquer les blocs try-catch à l'intérieur d'eux-mêmes!
Le code fait partie de ma plate-forme / framework bash . Il étend encore l'idée d'essayer et d'attraper avec des choses comme la gestion des erreurs avec backtrace et exceptions (ainsi que d'autres fonctionnalités intéressantes).
Voici le code qui est juste responsable de try & catch:
N'hésitez pas à utiliser, à fourche et à contribuer - c'est sur GitHub .
la source
my_output=$(try { code...; } catch { code...; })
Vous pouvez utiliser
trap
:try { block A } catch { block B } finally { block C }
Se traduit par:
la source
-E
drapeau, je pense, donc le piège se propage aux fonctionsIl y a tellement de solutions similaires qui fonctionnent probablement. Vous trouverez ci-dessous un moyen simple et pratique de réaliser try / catch, avec des explications dans les commentaires.
la source
bash
n'interrompt pas l'exécution en cours au cas où quelque chose détecte un état d'erreur (sauf si vous définissez l'-e
indicateur). Les langages de programmation qui le proposent letry/catch
font afin d' empêcher un "renflouement" à cause de cette situation particulière (donc généralement appelée "exception").Dans le
bash
, à la place, seule la commande en question se fermera avec un code de sortie supérieur à 0, indiquant cet état d'erreur. Vous pouvez vérifier cela bien sûr, mais comme il n'y a pas de vidage automatique de quoi que ce soit, un essai / capture n'a pas de sens. Il manque simplement ce contexte.Vous pouvez cependant simuler un renflouement en utilisant des sous-coques qui peuvent se terminer à un point que vous décidez:
Au lieu de cela
some_condition
avec un,if
vous pouvez également essayer une commande, et en cas d' échec (a un code de sortie supérieur à 0), renflouez:Malheureusement, en utilisant cette technique, vous êtes limité à 255 codes de sortie différents (1..255) et aucun objet d'exception décent ne peut être utilisé.
Si vous avez besoin de plus d'informations pour transmettre votre exception simulée, vous pouvez utiliser la sortie standard des sous-coquilles, mais c'est un peu compliqué et peut-être une autre question ;-)
En utilisant l'
-e
indicateur mentionné ci-dessus pour le shell, vous pouvez même supprimer cetteexit
déclaration explicite :la source
Comme tout le monde le dit, bash n'a pas de syntaxe try / catch prise en charge par le langage. Vous pouvez lancer bash avec l'
-e
argument ou utiliserset -e
à l'intérieur du script pour abandonner tout le processus bash si une commande a un code de sortie différent de zéro. (Vous pouvez égalementset +e
autoriser temporairement les commandes défaillantes.)Ainsi, une technique pour simuler un bloc try / catch consiste à lancer un sous-processus pour faire le travail avec
-e
enabled. Ensuite, dans le processus principal, vérifiez le code retour du sous-processus.Bash prend en charge les chaînes hérédoc, vous n'avez donc pas à écrire deux fichiers distincts pour gérer cela. Dans l'exemple ci-dessous, l'hérédoc TRY s'exécutera dans une instance bash distincte, avec
-e
activé, de sorte que le sous-processus se bloquera si une commande renvoie un code de sortie non nul. Ensuite, de retour dans le processus principal, nous pouvons vérifier le code retour pour gérer un bloc catch.Ce n'est pas un bloc try / catch pris en charge par la langue, mais il peut vous gratter une démangeaison similaire.
la source
Tu peux faire:
la source
Et vous avez des pièges http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html qui ne sont pas les mêmes, mais une autre technique que vous pouvez utiliser à cet effet
la source
Une chose très simple que j'utilise:
la source
||
est()
dedans, il fonctionnerait dans un sous-shell et sortirait, sans provoquer la sortie du shell principal. Utilisez{ }
plutôt le regroupement.Vous trouverez ci-dessous une copie complète du script simplifié utilisé dans mon autre réponse . Au-delà de la vérification d'erreur supplémentaire, il existe un alias qui permet à l'utilisateur de modifier le nom d'un alias existant. La syntaxe est donnée ci-dessous. Si le
new_alias
paramètre est omis, l'alias est supprimé.Le script complet est donné ci-dessous.
la source
Ci-dessous, un exemple de script implémenté
try/catch/finally
dans bash.Les exemples de scripts commencent par créer un fifo anonyme, qui est utilisé pour transmettre des messages de chaîne à partir d'un
command exception
outhrow
à la fin dutry
bloc le plus proche . Ici, les messages sont supprimés du fifo et placés dans une variable de tableau. Le statut est renvoyé à traversreturn
etexit
commandes et placé dans une autre variable. Pour entrer dans uncatch
bloc, ce statut ne doit pas être nul. Les autres exigences pour entrer dans uncatch
bloc sont transmises en tant que paramètres. Si la fin d'uncatch
bloc est atteinte, l'état est mis à zéro. Si la fin dufinally
bloc est atteinte et que l'état est toujours différent de zéro, un lancer implicite contenant les messages et l'état est exécuté. Le script nécessite l'appel de la fonctiontrycatchfinally
qui contient un gestionnaire d'exceptions non géré.La syntaxe de la
trycatchfinally
commande est donnée ci-dessous.L'
-c
option ajoute la pile d'appels aux messages d'exception.L'
-d
option active la sortie de débogage.L'
-e
option active les exceptions de commande.L'
-h
option permet à l'utilisateur de remplacer son propre gestionnaire d'exceptions de commande.L'
-k
option ajoute la pile d'appels à la sortie de débogage.L'
-o
option remplace le fichier de sortie par défaut qui est/dev/fd/2
.L'
-u
option permet à l'utilisateur de remplacer son propre gestionnaire d'exceptions non géré.L'
-v
option permet à l'utilisateur de renvoyer des valeurs via l'utilisation de la substitution de commande.Le
fifo
est le nom du fichier fifo.La fonction
function
est appelée par entrycatchfinally
tant que sous-processus.La syntaxe de la
catch
commande est donnée ci-dessous.Les options sont définies ci-dessous. La valeur de la première liste est le statut. Les valeurs subséquentes sont les messages. S'il y a plus de messages que de listes, les messages restants sont ignorés.
-e
signifie[[ $value == "$string" ]]
(la valeur doit correspondre à au moins une chaîne de la liste)-n
signifie[[ $value != "$string" ]]
(la valeur ne peut correspondre à aucune des chaînes de la liste)-o
signifie[[ $value != $pattern ]]
(la valeur ne peut correspondre à aucun des modèles de la liste)-p
signifie[[ $value == $pattern ]]
(la valeur a pour correspondre à au moins un modèle dans la liste)-r
signifie[[ $value =~ $regex ]]
(la valeur doit correspondre à au moins une expression régulière étendue dans la liste)-t
signifie[[ ! $value =~ $regex ]]
(la valeur ne peut correspondre à aucune des expressions régulières étendues dans la liste)Le
try/catch/finally
script est donné ci-dessous. Pour simplifier le script de cette réponse, la plupart des vérifications d'erreurs ont été supprimées. Cela a réduit la taille de 64%. Une copie complète de ce script peut être trouvée à mon autre réponse .Voici un exemple, qui suppose que le script ci-dessus est stocké dans le fichier nommé
simple
. Lemakefifo
fichier contient le script décrit dans cette réponse . L'hypothèse est faite que le fichier nommé4444kkkkk
n'existe pas, provoquant ainsi une exception. La sortie du message d'erreur de lals 4444kkkkk
commande est automatiquement supprimée jusqu'à l'intérieur ducatch
bloc approprié .Le script ci-dessus a été testé à l'aide de
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
. Le résultat de l'exécution de ce script est illustré ci-dessous.Un autre exemple qui utilise un
throw
peut être créé en remplaçant la fonctionMyFunction3
par le script illustré ci-dessous.La syntaxe de la
throw
commande est donnée ci-dessous. Si aucun paramètre n'est présent, l'état et les messages stockés dans les variables sont utilisés à la place.Le résultat de l'exécution du script modifié est illustré ci-dessous.
la source