Comment exécuter le script bash ligne par ligne?

93

Si j'entre l' option bash -x , il affichera toute la ligne. Mais le script s'exécutera normalement.

Comment puis-je exécuter ligne par ligne? Ensuite, je peux voir si cela fait la bonne chose, ou j'abandonne et corrige le bogue. Le même effet est mis un readdans chaque ligne.

Rodrigo
la source
1
Peut-être plus largement voir aussi stackoverflow.com/questions/951336/how-to-debug-a-bash-script/…
tripleee

Réponses:

126

Vous n'avez pas besoin de mettre une lecture dans everyline, ajoutez simplement un piège comme le suivant dans votre script bash, il a l'effet que vous voulez, par exemple.

#!/usr/bin/env bash
set -x
trap read debug

< YOUR CODE HERE >

Fonctionne, je viens de le tester avec bash v4.2.8 et v3.2.25.


VERSION AMÉLIORÉE

Si votre script lit le contenu de fichiers, la liste ci-dessus ne fonctionnera pas. Une solution de contournement pourrait ressembler à l'exemple suivant.

#!/usr/bin/env bash
echo "Press CTRL+C to proceed."
trap "pkill -f 'sleep 1h'" INT
trap "set +x ; sleep 1h ; set -x" DEBUG

< YOUR CODE HERE >

Pour arrêter le script, vous devrez le tuer d'un autre shell dans ce cas.


ALTERNATIVE1

Si vous souhaitez simplement attendre quelques secondes avant de passer à la commande suivante de votre script, l'exemple suivant pourrait fonctionner pour vous.

#!/usr/bin/env bash
trap "set +x; sleep 5; set -x" DEBUG

< YOUR CODE HERE >

J'ajoute set + x et set -x dans la commande trap pour rendre la sortie plus lisible.

mashup organique
la source
1
Alors, comment passez-vous à la ligne suivante (exécutez la commande suivante)?
David Doria
2
Il intercepte une lecture sur chaque commande. La seule chose que vous devez faire est d'appuyer sur Entrée pour passer à la commande suivante
organic-mashup
1
si vous avez des lignes de commande comme celle-ci "while read line; do echo $ line; done <somefile" cette méthode ne fonctionne pas car "trap read DEBUG" lit la ligne de somefile
mug896
3
Comment arrêtez-vous cela? Après avoir parcouru le script jusqu'à la fin, le shell agit comme si le script était toujours en cours d'exécution.
slashdottir
1
Remplacez par trap 'read -u1' debugpour remplacer le problème de redirection de lecture de fichier.
user3132194
23

Peut-être que le débogueur BASH est fait pour vous.


la source
3
C'est vraiment la meilleure solution. Il permet de visualiser la ligne avant son exécution (et bien plus encore). Sur la plupart des systèmes, il peut être installé avec apt-get install bashdb. Ensuite, il vous suffit d'exécuter bashdb your_command.sh, de taper step, puis d'appuyer sur le retour chariot après cela.
studgeek
1
@studgeek il n'est pas disponible sur Redhat / CentOS etc. donc je n'appellerais pas ça "la plupart des systèmes".
Sajuuk
@Sajuuk, il n'est peut-être pas emballé , mais il est absolument disponible .
Charles Duffy
macOS:brew install bashdb
boweeb
@CharlesDuffy: ce n'est pas non plus dans les dépôts Ubuntu par défaut.
Dan Dascalescu
2

Si votre script bash est vraiment un ensemble de commandes uniques que vous souhaitez exécuter une par une, vous pouvez faire quelque chose comme ceci, qui exécute chaque commande une par une lorsque vous incrémentez une variable LN, correspondant au numéro de ligne que vous souhaitez exécuter . Cela vous permet d'exécuter à nouveau la dernière commande très facilement, puis d'incrémenter simplement la variable pour passer à la commande suivante.

En supposant que vos commandes se trouvent dans un fichier "it.sh", exécutez ce qui suit, une par une.

$ cat it.sh
echo "hi there"
date
ls -la /etc/passwd

$ $(LN=1 && cat it.sh | head -n$LN | tail -n1)
"hi there"

$ $(LN=2 && cat it.sh | head -n$LN | tail -n1)
Wed Feb 28 10:58:52 AST 2018

$ $(LN=3 && cat it.sh | head -n$LN | tail -n1)
-rw-r--r-- 1 root wheel 6774 Oct 2 21:29 /etc/passwd
Brad Parks
la source
1

xargs: peut filtrer les lignes

cat .bashrc | xargs -0 -l -d \\n bash
  • -0 Traiter comme une entrée brute (pas d'échappatoire)
  • -l Séparer chaque ligne (pas par défaut pour les performances)
  • -d \\ n Le séparateur de ligne
Tinmarino
la source