web-dev-qa-db-fra.com

Comment déboguer un script bash?

Est-il possible de déboguer un script bash? Par exemple, quelque chose qui affiche une sorte de journal d'exécution du type "ligne 1", "ligne 2", etc.

147
corvus
sh -x script [arg1 ...]
bash -x script [arg1 ...]

Ceux-ci vous donnent une trace de ce qui est en cours d'exécution. (Voir aussi "Clarification" au bas de la réponse.)

Parfois, vous devez contrôler le débogage dans le script. Dans ce cas, comme Cheetoa rappelé moi, vous pouvez utiliser:

set -x

Cela active le débogage. Vous pouvez ensuite le désactiver à nouveau avec:

set +x

(Vous pouvez connaître l'état actuel du traçage en analysant $-, les indicateurs actuels, pour x.)

De plus, les shells fournissent généralement les options '-n' pour 'pas d'exécution' et '-v' pour le mode 'verbose'; vous pouvez les utiliser en combinaison pour voir si le shell pense pouvoir exécuter votre script, ce qui peut s'avérer utile si vous avez une citation non équilibrée quelque part.


Certains affirment que l'option '-x' dans Bash est différente des autres shells (voir les commentaires). Le Manuel Bash dit:

  • -X

    Imprimez une trace de commandes simples, de commandes for, de commandes case, de commandes select et de commandes arithmétiques for et de leurs arguments ou des listes de mots associées, une fois celles-ci développées et avant leur exécution. La valeur de la variable PS4 est développée et la valeur résultante est imprimée avant la commande et ses arguments développés. 

Cela ne semble pas indiquer un comportement différent du tout. Je ne vois aucune autre référence pertinente à «-x» dans le manuel. Il ne décrit pas les différences dans la séquence de démarrage.

Clarification: sur les systèmes tels qu'une machine Linux typique, où '/bin/sh' est un lien symbolique vers '/bin/bash' (ou partout où l'exécutable Bash est trouvé), les deux lignes de commande obtiennent le même effet que d'exécuter le script avec exécution. trace sur. Sur d'autres systèmes (par exemple, Solaris et certaines variantes plus modernes de Linux), /bin/sh n'est pas Bash, et les deux lignes de commande donneraient des résultats (légèrement) différents. Plus particulièrement, '/bin/sh' serait confondu par les constructions dans Bash qu'il ne reconnaît pas du tout. (Sous Solaris, /bin/sh est un Bourne Shell; sous Linux moderne, il s’agit parfois de Dash, un shell plus petit et plus strictement POSIX uniquement.) Lorsqu'elle est appelée par ce nom, la ligne 'Shebang' ('#!/bin/bash' contre '#!/bin/sh ') au début du fichier n’a aucun effet sur l’interprétation du contenu.

Le manuel de Bash a une section sur Mode Bash POSIX qui, contrairement à une version longue mais erronée de cette réponse (voir aussi les commentaires ci-dessous), décrit de manière très détaillée la différence entre 'Bash invoqué en tant que sh' et 'Bash invoqué en tant que bash'.

Lors du débogage d'un script Shell (Bash), il sera judicieux et sensé - voire nécessaire - d'utiliser le shell nommé dans la ligne Shebang avec l'option -x. Sinon, vous risquez d'obtenir un comportement différent lors du débogage lors de l'exécution du script.

183
Jonathan Leffler

J'ai utilisé les méthodes suivantes pour déboguer mon script.

set -e fait que le script s'arrête immédiatement si un programme externe renvoie un état de sortie autre que zéro. Cela est utile si votre script tente de gérer tous les cas d'erreur et qu'un échec doit être détecté.

set -x a été mentionné ci-dessus et est certainement la plus utile de toutes les méthodes de débogage.

set -n peut également être utile si vous souhaitez rechercher dans votre script des erreurs de syntaxe.

strace est également utile pour voir ce qui se passe. Particulièrement utile si vous n'avez pas écrit le script vous-même.

27
FD Gonthier

Cette réponse est valide et utile: https://stackoverflow.com/a/951352

Mais je trouve que les méthodes de débogage de script "standard" sont inefficaces, peu intuitives et difficiles à utiliser. Pour ceux qui sont habitués aux débogueurs graphiques sophistiqués qui mettent tout à portée de main et facilitent le travail pour des problèmes faciles (et possible pour des problèmes difficiles), ces solutions ne sont pas très satisfaisantes.

Ce que je fais est d'utiliser une combinaison de DDD et bashdb. Le premier exécute le dernier et le dernier exécute votre script. Ceci fournit une interface utilisateur multi-fenêtre avec la possibilité de parcourir le code dans le contexte et d'afficher les variables, la pile, etc., sans l'effort mental constant de maintenir le contexte dans votre tête ou de continuer à répertorier la source.

Il existe des conseils sur la manière de configurer cela ici: http://ubuntuforums.org/showthread.php?t=660223

12
Stabledog

Vous pouvez également écrire "set -x" dans le script.

9
Cheeto

J'ai trouvé l'utilitaire shellcheck et certaines personnes le trouvent peut-être intéressant https://github.com/koalaman/shellcheck

Un petit exemple:

$ cat test.sh 
ARRAY=("hello there" world)

for x in $ARRAY; do
  echo $x
done

$ shellcheck test.sh 

In test.sh line 3:
for x in $ARRAY; do
         ^-- SC2128: Expanding an array without an index only gives the first element.

corrigez le bogue, essayez d'abord ...

$ cat test.sh       
ARRAY=("hello there" world)

for x in ${ARRAY[@]}; do
  echo $x
done

$ shellcheck test.sh

In test.sh line 3:
for x in ${ARRAY[@]}; do
         ^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.

Essayons encore...

$ cat test.sh 
ARRAY=("hello there" world)

for x in "${ARRAY[@]}"; do
  echo $x
done

$ shellcheck test.sh

trouve maintenant!

C'est juste un petit exemple.

8
Equation Solver

J'ai construit un débogueur Bash. Juste essayer. J'espère que cela vous aidera https://sourceforge.net/projects/bashdebugingbash

2
abadjm

Installez VSCode , puis ajoutez l’extension bash debug et vous êtes prêt à déboguer en mode visuel. voir ici en action.

 enter image description here

2
yantaq

Je pense que vous pouvez essayer ce débogueur Bash: http://bashdb.sourceforge.net/ .

1
Nan Xiao

définir + x = @ECHO OFF, définir -x = @ECHO ON.


Vous pouvez ajouter l’option -xv au Shebang standard comme suit: 

#!/bin/bash -xv  

-x: Affiche les commandes et leurs arguments au fur et à mesure de leur exécution.
-v: Affiche les lignes d’entrée du shell au fur et à mesure de leur lecture. 


ltrace est un autre utilitaire Linux similaire à strace. Cependant, ltrace répertorie tous les appels de bibliothèque appelés dans un exécutable ou un processus en cours d'exécution. Son nom lui-même vient du traçage des appels de bibliothèque. Par exemple: 

ltrace ./executable <parameters>  
ltrace -p <PID>  

La source

1
Premraj

Quelques astuces pour déboguer bash scripts:

Utiliser set -[nvx]

En plus de 

set -x

et

set +x

pour arrêter le vidage.

Je voudrais parler de set -v qui dump est aussi petit que la sortie moins développée.

bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21

for arg in x v n nx nv nvx;do echo "- opts: $arg"
    bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
        set -$arg
        for i in {0..9};do
            echo $i
          done
        set +$arg
        echo Done.
eof
    sleep .02
  done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5

Vider les variables ou le traçage à la volée _

Pour tester certaines variables, j'utilise parfois ceci:

bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args

pour ajouter:

declare >&2 -p var1 var2

à la ligne 18 et en cours d'exécution du script (avec args), sans avoir à les modifier.

bien sûr, cela pourrait être utilisé pour ajouter set [+-][nvx]:

bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args

ajoutera declare -p v1 v2 >&2 après la ligne 18, set -x avant la ligne 22 et set +x avant la ligne 26.

petit échantillon:

bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
        seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8

Remarque: Le soin concernant $LINENO sera affecté par les modifications de {à la volée} _!

(Pour voir le script résultant sans s'exécuter, il suffit de déposer bash <( et ) arg1 arg2)

Pas à pas, temps d'exécution

Jetez un oeil à ma réponse sur la manière de profiler les scripts bash

0
F. Hauri

Il existe une grande quantité de détails sur la journalisation des scripts Shell via les variantes globales de Shell. Nous pouvons émuler un type de journalisation similaire dans le script Shell: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-Shell-scripts.html

Cet article contient des informations détaillées sur l’introduction de niveaux de journalisation tels que INFO, DEBUG, ERREUR . Des informations de traçage telles que la saisie de script, la sortie de script, la saisie de fonction, la sortie de fonction.

Exemple de journal:

 enter image description here

0
Piyush Chordia

Utilisez Eclipse avec les plugins shelled & basheclipse.

https://sourceforge.net/projects/shelled/?source=directoryhttps://sourceforge.net/projects/basheclipse/?source=directory

Pour shell: Téléchargez le zip et importez-le dans Eclipse via aide -> Installer un nouveau logiciel: archive locale Pour basheclipse: Copiez les fichiers JAR dans le répertoire dropins d’Eclipse.

Suivez les étapes fournit https://sourceforge.net/projects/basheclipse/files/?source=navbar

 enter image description here

J'ai écrit un tutoriel avec de nombreuses captures d'écran à http://dietrichschroff.blogspot.de/2017/07/bash-enabling-Eclipse-for-bash.html

0
Dietrich Schroff