web-dev-qa-db-fra.com

Comment afficher le numéro de ligne lors de l'exécution du script bash

J'ai un script de test qui contient beaucoup de commandes et génère beaucoup de sorties. J'utilise set -x ou set -v et set -e, de sorte que le script s'arrête en cas d'erreur. Cependant, il m'est toujours difficile de localiser la ligne qui a été arrêtée par l'exécution afin de localiser le problème. le numéro de ligne avant la commande exhibition généré par set -x? Ou toute méthode permettant de traiter mon problème d'emplacement de ligne de script serait d'une grande aide . Merci.

58
dspjm

Vous mentionnez que vous utilisez déjà -x. La variable PS4 indique que la valeur est l'invite imprimée avant que la ligne de commande ne soit répercutée lorsque l'option -x est définie et que la valeur par défaut est : suivie d'un espace.

Vous pouvez changer PS4 pour émettre la LINENO (Le numéro de ligne dans le script ou la fonction Shell en cours d'exécution).

Par exemple, si votre script se lit comme suit:

$ cat script
foo=10
echo ${foo}
echo $((2 + 2))

L’exécuter ainsi afficherait les numéros de ligne:

$ PS4='Line ${LINENO}: ' bash -x script
Line 1: foo=10
Line 2: echo 10
10
Line 3: echo 4
4

http://wiki.bash-hackers.org/scripting/debuggingtips donne le PS4 ultime qui générera tout ce dont vous aurez besoin pour le traçage:

export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
112
devnull

Dans Bash, $LINENO contient le numéro de ligne où le script est en cours d'exécution.

Si vous avez besoin de connaître le numéro de ligne où la fonction a été appelée, essayez $BASH_LINENO. Notez que cette variable est un tableau.

Par exemple:

#!/bin/bash       

function log() {
    echo "LINENO: ${LINENO}"
    echo "BASH_LINENO: ${BASH_LINENO[*]}"
}

function foo() {
    log "$@"
}

foo "$@"

Voir ici pour plus de détails sur les variables Bash.

21
Deqing

Contournement pour les obus sans LINENO

Dans un script assez sophistiqué, je ne voudrais pas voir tous les numéros de ligne; j'aimerais plutôt avoir le contrôle de la sortie. 

Définir une fonction

echo_line_no () {
    grep -n "$1" $0 |  sed "s/echo_line_no//" 
    # grep the line(s) containing input $1 with line numbers
    # replace the function name with nothing 
} # echo_line_no

Utilisez-le avec des citations comme 

echo_line_no "this is a simple comment with a line number"

La sortie est

16   "this is a simple comment with a line number"

si le numéro de cette ligne dans le fichier source est 16. 

Cela répond fondamentalement à la question Comment afficher le numéro de ligne lors de l'exécution du script bash pour les utilisateurs de cendres ou d'autres shells sans LINENO

Quelque chose à ajouter? 

Sûr. Pourquoi avez-vous besoin de cela? Comment travaillez-vous avec ça? Que pouvez-vous faire avec ça? Cette approche simple est-elle vraiment suffisante ou utile? Pourquoi voulez-vous bricoler avec ça?

Veut en savoir plus? Lire les réflexions sur le débogage

0
kklepper

Solution simple (mais puissante): Placez echo autour du code qui cause le problème et déplacez la echo ligne par ligne jusqu'à ce que les messages n'apparaissent plus à l'écran, car le script s'est arrêté à cause d'une erreur antérieure.

Une solution encore plus puissante: Installez bashdb le débogueur bash et déboguez le script ligne par ligne

0
hek2mgl