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 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 connectez-vous/effectuer certaines actions.
Ou peut-être que je vais tout cela mal?
J'ai testé avec ce qui suit:
#!/bin/bash
trap "ECHO $LINENO" ERR
echo hello | grep "asdf"
Et $LINENO
retourne 2. ne fonctionne pas.
Comme indiqué dans des commentaires, votre citation est fausse. Vous avez besoin de guillemets simples pour prévenir $LINENO
D'être étendu lorsque la ligne de piège est d'abord analysée.
Cela marche:
#! /bin/bash
err_report() {
echo "Error on line $1"
}
trap 'err_report $LINENO' ERR
echo hello | grep foo # This is line number 9
Le courir:
$ ./test.sh
Error on line 9
Vous pouvez également utiliser l'appelant Bash Bashetin ':
#!/bin/bash
err_report() {
echo "errexit on line $(caller)" >&2
}
trap err_report ERR
echo hello | grep foo
il imprime aussi le nom du fichier:
$ ./test.sh
errexit on line 9 ./test.sh
J'aime vraiment la réponse donnée par @mat ci-dessus. Construire sur ceci, j'ai écrit un petit assistant qui donne un peu plus de contexte pour l'erreur:
Nous pouvons inspecter le script pour la ligne qui a provoqué l'échec:
err() {
echo "Error occurred:"
awk 'NR>L-4 && NR<L+4 { printf "%-5d%3s%s\n",NR,(NR==L?">>>":""),$0 }' L=$1 $0
}
trap 'err $LINENO' ERR
Ici, c'est dans un petit script de test:
#!/bin/bash
set -e
err() {
echo "Error occurred:"
awk 'NR>L-4 && NR<L+4 { printf "%-5d%3s%s\n",NR,(NR==L?">>>":""),$0 }' L=$1 $0
}
trap 'err $LINENO' ERR
echo one
echo two
echo three
echo four
false
echo five
echo six
echo seven
echo eight
Quand nous l'exécutons, nous obtenons:
$ /tmp/test.sh
one
two
three
four
Error occurred:
12 echo two
13 echo three
14 echo four
15 >>>false
16 echo five
17 echo six
18 echo seven
Voici une autre version, inspirée de @sanmai et @unpythonic. Il affiche des lignes de script autour de l'erreur, avec des numéros de ligne et l'état de sortie - à l'aide de la queue et de la tête, ce qui semble plus simple que la solution AWK.
Affichage de cela comme deux lignes ici pour la lisibilité - vous pouvez rejoindre ces lignes en une seule si vous préférez (préserver le ;
):
trap 'echo >&2 "Error - exited with status $? at line $LINENO:";
pr -tn $0 | tail -n+$((LINENO - 3)) | head -n7' ERR
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 tirer le pseudo-signal ERR
, mais les autres cas présentent le contexte.
Exemple de sortie:
myscript.sh: line 27: blah: command not found
Error - exited with status 127 at line 27:
24 # Do something
25 lines=$(wc -l /etc/passwd)
26 # More stuff
27 blah
28
29 # Check time
30 time=$(date)