J'essaie de créer des rapports d'erreur à l'aide d'un piège pour appeler une fonction sur toutes les erreurs:
Trap "_func" ERR
Est-il possible d'obtenir de quelle ligne le signal ERR a été envoyé? La coquille est bash.
Si je le fais, je peux lire et signaler quelle commande a été utilisée et enregistrer / effectuer certaines actions.
Ou peut-être que je me trompe?
J'ai testé avec les éléments suivants:
#!/bin/bash
trap "ECHO $LINENO" ERR
echo hello | grep "asdf"
Et $LINENO
revient 2. Ne fonctionne pas.
bash
shell-script
error-handling
trap
Mechaflash
la source
la source
bashdb
. Il semble que le premier argument àtrap
contenir puisse contenir des variables évaluées dans le contexte souhaité. Celatrap 'echo $LINENO' ERR'
devrait donc fonctionner.trap 'echo $LINENO' ERR
. Le premier argument detrap
est l'intégralité duecho $LINENO
texte. C'est en bash.trap 'echo $LINENO' ERR
, avec des guillemets simples, pas des guillemets doubles. Avec la commande que vous avez écrite,$LINENO
est développée lorsque la ligne 2 est analysée, de sorte que le piège estecho 2
(ou plutôtECHO 2
, qui sortiraitbash: ECHO: command not found
).Réponses:
Comme indiqué dans les commentaires, votre citation est erronée. Vous avez besoin de guillemets simples pour éviter
$LINENO
d'être étendu lors de la première analyse de la ligne d'interruption.Cela marche:
Exécuter:
la source
echo hello | grep foo
ne semble pas me jeter d’erreur. Suis-je en train de mal comprendre quelque chose?grep
état de sortie est 0 s'il y a correspondance, 1 s'il n'y a pas de correspondance et> 1 pour une erreur. Vous pouvez vérifier le comportement de votre système avececho hello | grep foo; echo $?
Vous pouvez également utiliser l'appelant bash intégré:
il imprime également le nom de fichier:
la source
J'aime vraiment la réponse donnée par @Mat ci-dessus. Sur cette base, j'ai écrit un petit assistant qui donne un peu plus de contexte à l'erreur:
Nous pouvons inspecter le script pour la ligne qui a provoqué l'échec:
Le voici dans un petit script de test:
Lorsque nous l'exécutons, nous obtenons:
la source
$(caller)
les données de pour donner le contexte même si l'échec n'est pas dans le script actuel mais dans l'une de ses importations. Très bien quand même!Inspiré par d'autres réponses, voici un gestionnaire d'erreurs contextuelles plus simple:
Vous pouvez également utiliser awk au lieu de tail & head si nécessaire.
la source
Voici une autre version, inspirée de @sanmai et @unpythonic. Il montre les lignes de script autour de l'erreur, avec les numéros de ligne et l'état de sortie - en utilisant tail & head car cela semble plus simple que la solution awk.
En affichant ici deux lignes pour plus de lisibilité - vous pouvez joindre ces lignes en une seule si vous préférez (en préservant le
;
):Cela fonctionne assez bien avec
set -euo pipefail
( mode strict non officiel ) - toute erreur de variable non définie donne un numéro de ligne sans déclencher leERR
pseudo-signal, mais les autres cas montrent le contexte.Exemple de sortie:
la source
Oui,
LINENO
et lesBASH_LINENO
variables sont très utiles pour obtenir la ligne d'échec et les lignes qui y mènent.Non, il manque juste une
-q
option avec grep ...... Avec l'
-q
optiongrep
reviendra0
pourtrue
et1
pourfalse
. Et dans Bash ce n'esttrap
pasTrap
...Voici un trappeur que vous pourriez trouver utile pour déboguer des choses qui ont un peu plus de complexité cyclomatique ...
failure.sh
... et un exemple de script d'utilisation pour exposer les différences subtiles dans la façon de définir le piège ci-dessus pour le traçage de fonction aussi ...
example_usage.sh
Ce qui précède a été testé sur Bash version 4+, alors laissez un commentaire si quelque chose pour les versions antérieures à quatre est nécessaire, ou ouvrez un problème s'il ne parvient pas à intercepter les échecs sur les systèmes avec une version minimale de quatre.
Les principaux plats à emporter sont ...
-E
fait bouillonner les erreurs dans les fonctions-o functrace
causes permet plus de verbosité lorsque quelque chose dans une fonction échoueLes guillemets simples sont utilisés autour de l'appel de fonction et les guillemets doubles sont autour des arguments individuels
Les références à
LINENO
etBASH_LINENO
sont passées à la place des valeurs actuelles, bien que cela puisse être raccourci dans les versions ultérieures de Linked to Trap, de sorte que la ligne d'échec finale la rende en sortieLes valeurs de
BASH_COMMAND
et exit status ($?
) sont transmises, d'abord pour obtenir la commande qui a renvoyé une erreur, et ensuite pour s'assurer que l'interruption ne se déclenche pas sur les états sans erreurEt tandis que d'autres peuvent être en désaccord, je trouve qu'il est plus facile de créer un tableau de sortie et d'utiliser printf pour imprimer chaque élément du tableau sur sa propre ligne ...
... aussi le
>&2
bit à la fin fait que les erreurs vont là où elles devraient (erreur standard), et permet de capturer uniquement les erreurs ...Comme le montrent ces exemples et d' autres sur Stack Overflow, il existe de nombreuses façons de créer une aide au débogage à l'aide d'utilitaires intégrés.
la source