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.
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.
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.
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
Vous pouvez également écrire "set -x" dans le script.
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.
J'ai construit un débogueur Bash. Juste essayer. J'espère que cela vous aidera https://sourceforge.net/projects/bashdebugingbash
Je pense que vous pouvez essayer ce débogueur Bash: http://bashdb.sourceforge.net/ .
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>
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
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.
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
)
Jetez un oeil à ma réponse sur la manière de profiler les scripts bash
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:
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
J'ai écrit un tutoriel avec de nombreuses captures d'écran à http://dietrichschroff.blogspot.de/2017/07/bash-enabling-Eclipse-for-bash.html