GNU/Linux >> Tutoriels Linux >  >> Linux

Comment puis-je trouver le numéro de ligne dans Bash lorsqu'une erreur s'est produite ?

Plutôt que d'utiliser votre fonction, j'utiliserais plutôt cette méthode :

$ cat yael.bash
#!/bin/bash

set -eE -o functrace

file1=f1
file2=f2
file3=f3
file4=f4

failure() {
  local lineno=$1
  local msg=$2
  echo "Failed at $lineno: $msg"
}
trap 'failure ${LINENO} "$BASH_COMMAND"' ERR

cp -- "$file1" "$file2"
cp -- "$file3" "$file4"

Cela fonctionne en piégeant sur ERR puis en appelant le failure() fonction avec le numéro de ligne actuel + la commande bash qui a été exécutée.

Exemple

Ici je n'ai pas pris soin de créer les fichiers, f1 , f2 , f3 , ou f4 . Lorsque j'exécute le script ci-dessus :

$ ./yael.bash
cp: cannot stat ‘f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"

Il échoue, rapportant le numéro de ligne plus la commande qui a été exécutée.


En plus de LINENO contenant le numéro de la ligne courante, il y a les BASH_LINENO et FUNCNAME (et BASH_SOURCE ) des tableaux contenant les noms de fonction et les numéros de ligne à partir desquels ils sont appelés.

Vous pourriez donc faire quelque chose comme ceci :

#!/bin/bash

error() {
        printf "'%s' failed with exit code %d in function '%s' at line %d.\n" "${1-something}" "$?" "${FUNCNAME[1]}" "${BASH_LINENO[0]}"
}

foo() {
        ( exit   0 ) || error "this thing"
        ( exit 123 ) || error "that thing"
}

foo

Exécution qui imprimerait

'that thing' failed with exit code 123 in function 'foo' at line 9.

Si vous utilisez set -e , ou trap ... ERR pour détecter automatiquement les erreurs, notez qu'ils ont quelques mises en garde. Il est également plus difficile d'inclure une description de ce que le script faisait à l'époque (comme vous l'avez fait dans votre exemple), bien que cela puisse être plus utile pour un utilisateur ordinaire que le simple numéro de ligne.

Voir par ex. ceux-ci pour les problèmes avec set -e et autres :

  • Pourquoi set -e ne fonctionne-t-il pas dans les sous-shells avec des parenthèses () suivies d'une liste OR || ?
  • bash -e se termine lorsque let ou expr est évalué à 0
  • BashFAQ 105 :Pourquoi set -e (ou set -o errexit, ou trap ERR) ne fait-il pas ce que j'attendais ?

Bash a une variable intégrée $LINENO qui est remplacé par le numéro de ligne actuel dans une instruction, vous pouvez donc le faire

in_case_fail $? "at $LINENO: cp $file1 $file2"

Vous pouvez également essayer d'utiliser trap ... ERR qui s'exécute lorsqu'une commande échoue (si le résultat n'est pas testé). Ex :

trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR

Alors si une commande comme cp $file1 $file2 échoue, vous obtiendrez le message d'erreur avec le numéro de ligne et une sortie. Vous trouverez également la commande en erreur dans la variable $BASH_COMMAND (mais pas de redirections, etc.).


Linux
  1. Comment trouver le nombre de lignes verticales disponibles dans le terminal ?

  2. Linux - Comment afficher constamment le numéro de ligne lors de la navigation dans Nano ?

  3. Comment définir les paramètres lorsque Pipe Bash Script to Bash ?

  4. Comment lire l'avant-dernière ligne d'un fichier avec Bash ?

  5. Comment puis-je compter le nombre de caractères dans une variable Bash

Comment commenter dans Bash

Comment lire un fichier ligne par ligne dans Bash

Comment trouver le numéro de port d'un service sous Linux

Comment trouver qui a redémarré le système Linux et quand

Comment trouver des fichiers sur la ligne de commande Ubuntu

Comment effacer le numéro de ligne dans Vim lors de la copie ?