Existe-t-il un moyen de déboguer un script bash? Par exemple, quelque chose qui imprime une sorte de journal d'exécution comme "appelant la ligne 1", "appelant la ligne 2" etc.
Ceux-ci vous donnent une trace de ce qui est en cours d'exécution. (Voir aussi «Clarification» en bas de la réponse.)
Parfois, vous devez contrôler le débogage dans le script. Dans ce cas, comme Cheeto me l'a rappelé , vous pouvez utiliser:
set-x
Cela active le débogage. Vous pouvez ensuite le désactiver à nouveau avec:
set+x
(Vous pouvez trouver l'état de traçage actuel en analysant $-, les indicateurs actuels, pour x.)
De plus, les shells fournissent généralement les options « -n» pour «aucune exécution» et « -v» pour le mode «verbeux»; vous pouvez les utiliser en combinaison pour voir si le shell pense pouvoir exécuter votre script - parfois utile si vous avez un devis déséquilibré quelque part.
-xL'option « » de Bash est différente des autres shells (voir les commentaires). Le manuel Bash dit:
-X
Imprimez une trace des commandes simples, des forcommandes, des casecommandes, des selectcommandes et des forcommandes arithmétiques et de leurs arguments ou des listes de mots associés après leur développement et avant leur exécution. La valeur de la PS4variable 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 du tout indiquer un comportement différent. 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 des systèmes tels qu'une machine Linux typique, où « /bin/sh» est un lien symbolique vers « /bin/bash» (ou partout où se trouve l'exécutable Bash), les deux lignes de commande obtiennent l'effet équivalent de l'exécution du script avec la trace d'exécution activée. Sur d'autres systèmes (par exemple, Solaris et certaines variantes plus modernes de Linux), ce /bin/shn'est pas Bash, et les deux lignes de commande donneraient des résultats (légèrement) différents. Plus particulièrement, ' /bin/sh' serait dérouté par des constructions dans Bash qu'il ne reconnaît pas du tout. (Sur Solaris, /bin/shest un shell Bourne; sur Linux moderne, il s'agit parfois de Dash - un shell plus petit, plus strictement réservé à POSIX.) Lorsqu'elle est appelée par un nom comme celui-ci, la ligne 'shebang' (' #!/bin/bash' vs '#!/bin/sh'
Le manuel Bash contient une section sur le mode Bash POSIX qui, contrairement à une version ancienne mais erronée de cette réponse (voir aussi les commentaires ci-dessous), décrit en détail la différence entre `` Bash invoqué comme sh'' et `` Bash invoqué comme bash».
Lors du débogage d'un script shell (Bash), il sera judicieux et sensé - nécessaire même - d'utiliser le shell nommé dans la ligne shebang avec l' -xoption. Sinon, vous pouvez (obtiendrez?) Un comportement différent lors du débogage de lors de l'exécution du script.
Il a spécifié un bashscript. Et exécuter un script bash avec le sh -xfera se comporter complètement différent! Veuillez mettre à jour votre réponse.
lhunath le
1
@lhunath: En quoi 'sh -x' (ou 'bash -x') fait-il qu'un script se comporte complètement différemment? De toute évidence, il envoie des informations de trace à stderr; c'est une donnée (mais non mentionnée dans ma réponse). Mais quoi d'autre? J'utilise «bash» comme «sh» sous Linux et MacOS X et je n'ai pas remarqué de problème sérieux.
Jonathan Leffler
6
Il existe des différences, au démarrage et à l'exécution. Ils sont entièrement documentés dans la distribution Bash.
TheBonsai
4
Voici un lien vers le bash doc: gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files 'Si Bash est appelé avec le nom sh, il essaie d'imiter le comportement de démarrage des versions historiques de sh comme aussi étroitement que possible, tout en se conformant également à la norme posix '
thethinman
6
Et utilisez l'invite PS4 pour donner des informations plus utiles comme:export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
estani
28
J'ai utilisé les méthodes suivantes pour déboguer mon script.
set -earrête immédiatement le script si un programme externe renvoie un statut de sortie différent de zéro. Ceci est utile si votre script tente de gérer tous les cas d'erreur et lorsqu'un échec de le faire doit être intercepté.
set -x a été mentionnée 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 vérifier votre script pour les erreurs de syntaxe.
straceest également utile pour voir ce qui se passe. Particulièrement utile si vous n'avez pas écrit le script vous-même.
Le suivi d'un script (c'est-à-dire le suivi d'un shell exécutant le script) est une étrange méthode de débogage du shell (mais peut fonctionner pour un ensemble limité de problèmes).
TheBonsai
1
J'avoue que c'est étrange et aussi très verbeux, mais si vous limitez la sortie de strace à quelques appels système, cela devient utile.
1
Notez que cela strace -fest nécessaire si vous souhaitez également rechercher des erreurs dans les processus démarrés par le script. (ce qui le rend beaucoup plus verbeux, mais toujours utile si vous le limitez aux appels système qui vous intéressent).
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 GUI sophistiqués qui mettent tout à portée de main et facilitent le travail pour les problèmes faciles (et possibles pour les problèmes difficiles), ces solutions ne sont pas très satisfaisantes.
Ce que je fais, c'est utiliser une combinaison de DDD et bashdb. Le premier exécute le second et le second exécute votre script. Cela fournit une interface utilisateur multi-fenêtres avec la possibilité de parcourir le code en contexte et d'afficher les variables, la pile, etc., sans l'effort mental constant pour maintenir le contexte dans votre tête ou continuer à réinscrire la source.
Je viens de découvrir ddd grâce à ta réponse. Dans Ubuntu 12.04.3 (64 bits), la version apt-sources ne fonctionne pas. J'ai dû compiler et installer à partir des sources pour commencer à déboguer mon script bash. Les instructions ici - askubuntu.com/questions/156906/… ont aidé.
chronodekar
Oui, c'est un problème. Je l'ai résolu il y a quelque temps avec des scripts - 'dddbash' installe / construit DDD, supprime l'ancienne version si elle est fausse, installe bashdb, etc. (La réponse a été modifiée avec cette information maintenant)
Stabledog
10
Vous pouvez également écrire "set -x" dans le script.
$ cat test.sh
ARRAY=("hello there" world)for x in $ARRAY;do
echo $xdone
$ 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 $xdone
$ shellcheck test.shIn test.sh line 3:for x in ${ARRAY[@]};do^-- SC2068:Double quote array expansions, otherwise they're like $* and break on spaces.
Pour shelled: Téléchargez le zip et importez-le dans eclipse via l'aide -> installez un nouveau logiciel: archive locale Pour basheclipse: Copiez les jars dans le répertoire dropins d'eclipse
Ceci est une réponse à la limite des liens uniquement (voir également ici ). Vous devriez élargir votre réponse pour inclure ici autant d'informations que possible, au moins le minimum nécessaire pour accomplir réellement ce que vous suggérez, et utiliser les liens uniquement à titre de référence. Fondamentalement, les publications sur Stack Overflow (et l'ensemble de Stack Exchange) doivent être autonomes. Cela signifie que votre réponse doit contenir suffisamment d'informations pour que le lecteur n'ait pas besoin de quitter le site pour obtenir des directions. À l'heure actuelle, ce n'est pas le cas pour cette réponse.
Makyen
c'est la première réponse que j'ai trouvée après en avoir examiné beaucoup qui montre en fait qu'un véritable débogage est possible. Les réponses standard "set + x" correspondent parfaitement à une réponse autonome mais ignorent presque volontairement les vraies questions sur le vrai débogage. J'applaudis cette réponse 👏
BDB est actuellement pris en charge en anglais et en espagnol. Pour changer la langue, éditez le fichier / etc / default / bdb
abadjm
la capture d'écran semble intéressante mais je n'ai pas pu la faire exécuter "bdb.sh: ligne 32: bdbSTR [1]: variable non liée"; btw montrera-t-il les valeurs actuelles de toutes les variables définies à chaque étape que nous faisons sur le code?
Aquarius Power
2
set + x = @ECHO OFF, set -x = @ECHO ON.
Vous pouvez ajouter une -xvoption 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.
ltraceest un autre utilitaire Linux similaire à strace. Cependant, ltraceré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:
Il y a une bonne quantité de détails sur la journalisation des scripts shell via des variables globales de shell. Nous pouvons émuler le même type de journalisation dans le script shell: cubicrace.com/2016/03/efficient-logging-mechnism-in-shell.html
Le message contient des détails sur l'introduction de niveaux de journal tels que INFO, DEBUG, ERROR. Traçage des détails tels que l'entrée de script, la sortie de script, l'entrée de fonction, la sortie de fonction.
Réponses:
Ceux-ci vous donnent une trace de ce qui est en cours d'exécution. (Voir aussi «Clarification» en bas de la réponse.)
Parfois, vous devez contrôler le débogage dans le script. Dans ce cas, comme Cheeto me l'a rappelé , vous pouvez utiliser:
Cela active le débogage. Vous pouvez ensuite le désactiver à nouveau avec:
(Vous pouvez trouver l'état de traçage actuel en analysant
$-
, les indicateurs actuels, pourx
.)De plus, les shells fournissent généralement les options «
-n
» pour «aucune exécution» et «-v
» pour le mode «verbeux»; vous pouvez les utiliser en combinaison pour voir si le shell pense pouvoir exécuter votre script - parfois utile si vous avez un devis déséquilibré quelque part.-x
L'option « » de Bash est différente des autres shells (voir les commentaires). Le manuel Bash dit:-X
Imprimez une trace des commandes simples, des
for
commandes, descase
commandes, desselect
commandes et desfor
commandes arithmétiques et de leurs arguments ou des listes de mots associés après leur développement et avant leur exécution. La valeur de laPS4
variable 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 du tout indiquer un comportement différent. 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 des systèmes tels qu'une machine Linux typique, où «
/bin/sh
» est un lien symbolique vers «/bin/bash
» (ou partout où se trouve l'exécutable Bash), les deux lignes de commande obtiennent l'effet équivalent de l'exécution du script avec la trace d'exécution activée. Sur d'autres systèmes (par exemple, Solaris et certaines variantes plus modernes de Linux), ce/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 dérouté par des constructions dans Bash qu'il ne reconnaît pas du tout. (Sur Solaris,/bin/sh
est un shell Bourne; sur Linux moderne, il s'agit parfois de Dash - un shell plus petit, plus strictement réservé à POSIX.) Lorsqu'elle est appelée par un nom comme celui-ci, la ligne 'shebang' ('#!/bin/bash
' vs'#!/bin/sh
'Le manuel Bash contient une section sur le mode Bash POSIX qui, contrairement à une version ancienne mais erronée de cette réponse (voir aussi les commentaires ci-dessous), décrit en détail la différence entre `` Bash invoqué comme
sh
'' et `` Bash invoqué commebash
».Lors du débogage d'un script shell (Bash), il sera judicieux et sensé - nécessaire même - d'utiliser le shell nommé dans la ligne shebang avec l'
-x
option. Sinon, vous pouvez (obtiendrez?) Un comportement différent lors du débogage de lors de l'exécution du script.la source
bash
script. Et exécuter un script bash avec lesh -x
fera se comporter complètement différent! Veuillez mettre à jour votre réponse.export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
J'ai utilisé les méthodes suivantes pour déboguer mon script.
set -e
arrête immédiatement le script si un programme externe renvoie un statut de sortie différent de zéro. Ceci est utile si votre script tente de gérer tous les cas d'erreur et lorsqu'un échec de le faire doit être intercepté.set -x
a été mentionnée 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 vérifier votre script pour les 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.la source
strace -f
est nécessaire si vous souhaitez également rechercher des erreurs dans les processus démarrés par le script. (ce qui le rend beaucoup plus verbeux, mais toujours utile si vous le limitez aux appels système qui vous intéressent).set -e
est ... controversé .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 GUI sophistiqués qui mettent tout à portée de main et facilitent le travail pour les problèmes faciles (et possibles pour les problèmes difficiles), ces solutions ne sont pas très satisfaisantes.
Ce que je fais, c'est utiliser une combinaison de DDD et bashdb. Le premier exécute le second et le second exécute votre script. Cela fournit une interface utilisateur multi-fenêtres avec la possibilité de parcourir le code en contexte et d'afficher les variables, la pile, etc., sans l'effort mental constant pour maintenir le contexte dans votre tête ou continuer à réinscrire la source.
Il y a des conseils sur la configuration ici: http://ubuntuforums.org/showthread.php?t=660223
la source
Vous pouvez également écrire "set -x" dans le script.
la source
J'ai trouvé l'utilitaire shellcheck et certains le trouvent peut-être intéressant https://github.com/koalaman/shellcheck
Un petit exemple:
corrigez le bogue, essayez d'abord ...
Essayons encore...
trouve maintenant!
C'est juste un petit exemple.
la source
Installez VSCode , puis ajoutez l'extension de débogage bash et vous êtes prêt à déboguer en mode visuel. voir Ici en action.
la source
Utilisez eclipse avec les plugins shelled & basheclipse.
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
Pour shelled: Téléchargez le zip et importez-le dans eclipse via l'aide -> installez un nouveau logiciel: archive locale Pour basheclipse: Copiez les jars dans le répertoire dropins d'eclipse
Suivez les étapes fournies https://sourceforge.net/projects/basheclipse/files/?source=navbar
J'ai écrit un tutoriel avec de nombreuses captures d'écran sur http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html
la source
J'ai construit un débogueur Bash. Essayez-le. J'espère que cela aidera https://sourceforge.net/projects/bashdebugingbash
la source
Vous pouvez ajouter une
-xv
option au Shebang standard comme suit:-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:La source
la source
Je pense que vous pouvez essayer ce débogueur Bash: http://bashdb.sourceforge.net/ .
la source
Une astuce pour déboguer frapper scripts:
En utilisant
set -[nvx]
En plus de
et
pour arrêter le vidage.
Je voudrais parler d'un
set -v
dump aussi petit que d'une sortie moins développée.Vider les variables ou le traçage à la volée
Pour tester certaines variables, j'utilise parfois ceci:
pour ajouter:
à la ligne 18 et exécutant le script résultant (avec args ), sans avoir à les éditer.
bien sûr, cela pourrait être utilisé pour ajouter
set [+-][nvx]
:ajoutera
declare -p v1 v2 >&2
après la ligne 18,set -x
avant la ligne 22 etset +x
avant la ligne 26.petit échantillon:
Remarque: Care about
$LINENO
sera affecté par les modifications à la volée !(Pour voir le script résultant sans s'exécuter, déposez simplement
bash <(
et) arg1 arg2
)Pas à pas, temps d'exécution
Jetez un œil à ma réponse sur la façon de profiler les scripts bash
la source
Il y a une bonne quantité de détails sur la journalisation des scripts shell via des variables globales de shell. Nous pouvons émuler le même type de journalisation dans un script shell: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
Le message contient des détails sur l'introduction de niveaux de journal tels que INFO, DEBUG, ERROR. Traçage des détails tels que l'entrée de script, la sortie de script, l'entrée de fonction, la sortie de fonction.
Exemple de journal:
la source