Comment vérifier quelle ligne d'un script bash est en cours d'exécution

15

Existe-t-il un moyen de vérifier quel numéro de ligne d'un bashscript est exécuté "en ce moment"?

Utiliser un bash -x script.shlook prometteur; cependant, je dois obtenir le numéro de ligne actuel.

user224371
la source

Réponses:

20

Combinez xtraceavec l' PS4intérieur du script:

$ cat test.sh 
#!/usr/bin/env bash
set -x
PS4='+${LINENO}: '

sleep 1m
sleep 1d
$ timeout 5 ./test.sh
+3: PS4='+${LINENO}: '
+5: sleep 1m

ou dans le shell parent :

$ cat test.sh 
sleep 1m
sleep 1d
$ export PS4='+${LINENO}: '
$ timeout 5 bash -x ./test.sh
+1: sleep 1m
l0b0
la source
10

Oui, il existe un moyen.
Il existe un tableau de numéros de ligne où une fonction a été appelée.

Définissez cette fonction:

f(){ echo "${BASH_LINENO[-2]}"; }

Et appelez fà n'importe quelle ligne que vous voulez le numéro de ligne, par exemple:

#!/bin/bash


f(){ echo "${BASH_LINENO[-2]}"; }

f

echo next1
f

echo next2
f

echo next 3
f

Imprime:

6
next 1
9
next 2
12
next 3
15

Il pourrait être développé pour montrer la piste des fonctions appelées:

#!/bin/bash

f(){
    for ((i=${#BASH_LINENO[@]}-1;i>=0;i--)); do
    printf '<%s:%s> ' "${FUNCNAME[i]}" "${BASH_LINENO[i]}";
    done
    echo "$LINENO"
 }

SomeOtherFunction(){ echo -n "test the line numbering:  "; f; }

f

echo next 1
echo -n "    This line numbering:  "; f
SomeOtherFunction

echo next 2
echo -n "    This line numbering:  "; f
SomeOtherFunction

echo next 3
echo -n "    This line numbering:  "; f

Qui imprimera:

$ ./script
<main:0> <f:12> 7
next 1
    This line numbering:  <main:0> <f:15> 7
test the line numbering:  <main:0> <SomeOtherFunction:16> <f:10> 7
next 2
    This line numbering:  <main:0> <f:19> 7
test the line numbering:  <main:0> <SomeOtherFunction:20> <f:10> 7
next 3
    This line numbering:  <main:0> <f:23> 7

Notez qu'au dessus la echo "$LINENO"sortie est toujours la même (7 dans ce cas).

Sorontar
la source
7

Voici une solution qui emprunte des parties des réponses de l0b0 et de DopeGhoti (et, dans une moindre mesure, de sorontar ). Comme ces réponses, la mienne utilise $LINENOpour découvrir le numéro de ligne; contrairement à eux, j'utilise trappour déclencher le reporting. La trapcommande de bash est décrite dans bash (1) :

trap [-lp] [[arg] sigspec ...]

    La commande arg doit être lue et exécutée lorsque le shell reçoit le ou les signaux sigspec . … ⁠ ︙
    … Si une sigspec est DEBUG , la commande arg est exécutée avant chaque commande simple , forcommande, casecommande, selectcommande, chaque forcommande arithmétique et avant que la première commande ne s'exécute dans une fonction shell…

Donc ce script:

$ cat -n myscript
     1  #!/bin/bash
     2  trap 'printf "%3d: " "$LINENO"' DEBUG
     3  date
     4  sleep 30
     5  date
     6  sleep \
     7        11
     8  date
     9
    10  ls -l
    11  for f in *
    12  do
    13          echo "$f"  &&
    14                         ls -ld "$f"
    15  done
    16
    17  for ((i=0; i<3; i++))
    18  do
    19          echo "i = $i"; date
    20  done
    21
    22  echo $((5+25+12))
$

exécute la printf "%3d: " "$LINENO"commande avant chaque commande du script et produit cette sortie:

$ ./myscript
  3: mer., 05 avr. 2017 10:16:17 AM
  4: 5: mer., 05 avr. 2017 10:16:47 AM
  7: 8: mer., 05 avr. 2017 10:16:58 AM
 10: total 4
-rwxr-xr-x 1 myusername mygroup 221 5 avril 10:01 myscript
-rwxr-xr-x 1 myusername mygroup 252 5 avril 10:01 myscript2
-rw-r - r-- 1 myusername mygroup 132 5 avril 09:59 myscript2.log
-rw-r - r-- 1 myusername mygroup   45 5 avril 08:34 other_file
 11: 13: myscript
 14: -rwxr-xr-x 1 myusername mygroup 221 5 avril 10:01 myscript
 11: 13: myscript2
 14: -rwxr-xr-x 1 myusername mygroup 252 5 avril 10:01 myscript2
 11: 13: myscript2.log
 14: -rw-r - r-- 1 myusername mygroup 132 5 avril 09:59 myscript2.log
 11: 13: autre_fichier
 14: -rw-r - r-- 1 myusername mygroup   45 5 avril 08:34 other_file
 17: 17: 19: i = 0
 19: mer., 05 avr. 2017 10:16:59 AM
 17: 17: 19: i = 1
 19: mer., 05 avr. 2017 10:16:59 AM
 17: 17: 19: i = 2
 19: mer., 05 avr. 2017 10:16:59 AM
 17: 17: 22: 42
$

Remarques:

  • Comme la réponse de l0b0 , c'est peu invasif - il suffit d'ajouter la ligne 2.
  • Contrairement à la réponse de l0b0 , cela n'affiche pas les commandes elles-mêmes - mais vous ne l'avez pas demandé pour cela.
  • Le second sleep, qui couvre les lignes de script 6 et 7, est signalé comme la ligne 7.
  • La ligne 11 ( for f in *) est signalée une fois avant chaque itération de cette forboucle.
  • echo "$f"et ls -ld "$f"sont correctement signalés sur leurs lignes respectives (13 et 14).
  • La ligne 17 ( for ((i=0; i<3; i++))) est signalée deux fois avant chaque itération de cette forboucle, et deux fois après la dernière itération.
  • Contrairement à set -x, LINENOet PS4 (qui sont spécifiés par la norme POSIX), DEBUG trapest une extension bash et ne fonctionnera pas dans tous les shells.
  • Le DEBUG trappeut exécuter n'importe quelle commande et n'est pas limité à l'écriture dans la sortie standard ou l'erreur standard du script.

La question dit: «vérifiez quel numéro de ligne d'un script bash est exécuté« en ce moment »» sans spécifier d'interface utilisateur. Une autre approche consiste à écrire continuellement le numéro de ligne actuel dans un fichier journal:

$ diff myscript myscript2
2c2
<trap 'printf "% 3d:" "$ LINENO"' DEBUG
---
> exec 6> myscript2.log && trap 'printf "% 3d \ n" "$ LINENO"> & 6' DEBUG
$ ./myscript2
Mer.05 avril 2017 10:23:50
Mer.05 avril 2017 10:24:20
Mer.05 avril 2017 10:24:31
total 4
-rwxr-xr-x 1 myusername mygroup 221 5 avril 10:01 myscript
-rwxr-xr-x 1 myusername mygroup 252 5 avril 10:01 myscript2
-rw-r - r-- 1 myusername mygroup   24 avril 5 10:23 myscript2.log
-rw-r - r-- 1 myusername mygroup   45 5 avril 08:34 other_file
myscript
-rwxr-xr-x 1 myusername mygroup 221 5 avril 10:01 myscript
myscript2
-rwxr-xr-x 1 myusername mygroup 252 5 avril 10:01 myscript2
myscript2.log
-rw-r - r-- 1 myusername mygroup   60 5 avril 10:23 myscript2.log
autre_fichier
-rw-r - r-- 1 myusername mygroup   45 5 avril 08:34 other_file
i = 0
Mer.05 avril 2017 10:24:31
i = 1
Mer.05 avril 2017 10:24:31
i = 2
Mer.05 avril 2017 10:24:31
42
$

Nous pouvons surveiller l'exécution de ce script en surveillant le contenu du myscript2.logfichier à partir d'un autre terminal. Par exemple, au cours de la seconde sleep,

$ tail myscript2.log
  3
  4
  5
  7
G-Man dit «Réintègre Monica»
la source
6

Vous pouvez le faire echo $LINENOdans un script et il devrait afficher n'importe quelle ligne sur laquelle cette commande se trouve.

#!/bin/bash
echo $LINENO

$ ./foo.sh
2
DopeGhoti
la source
-1
#!/bin/bash -x

Ajoutez ce "-x" au début de votre script. Ensuite, chaque fois que vous exécutez le script, il fera écho à la ligne que votre script exécute. comme un arbre d'exécution de votre script.

Pavan Shah
la source
4
Le PO a déjà rejeté cette suggestion comme étant insatisfaisante.
G-Man dit `` Réinstalle Monica '' le