Come verificare quale riga di uno script bash è in esecuzione


15

C'è un modo per verificare quale numero di riga di uno bashscript viene eseguito "in questo momento"?

L'uso bash -x script.shsembra promettente; tuttavia, devo ottenere il numero di riga corrente.

Risposte:


20

Combina xtracecon PS4all'interno dello 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

o nella shell genitore :

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

10

Sì, c'è un modo.
Esiste una matrice di numeri di riga in cui è stata chiamata una funzione.

Definisci questa funzione:

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

E chiama fin qualsiasi linea desideri il numero di linea, ad esempio:

#!/bin/bash


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

f

echo next1
f

echo next2
f

echo next 3
f

Stampa:

6
next 1
9
next 2
12
next 3
15

Potrebbe essere espanso per mostrare la scia di funzioni chiamate:

#!/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

Che stamperà:

$ ./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

Si noti che sopra l' echo "$LINENO"uscita è sempre la stessa (7 in questo caso).


7

Ecco una soluzione che prende in prestito parti delle risposte di l0b0 e DopeGhoti (e, in misura minore, di sorontar ). Come quelle risposte, la mia usa $LINENOper scoprire il numero di riga; a differenza di loro, utilizzo trapper attivare la segnalazione. Il trapcomando di bash è descritto in bash (1) :

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

    Il comando arg deve essere letto ed eseguito quando la shell riceve segnali sigspec . ... ⁠ ︙
    ... Se un sigspec è DEBUG , il comando arg viene eseguito prima di ogni semplice comando , forcomando, casecomando, selectcomando, ogni forcomando aritmetico e prima che il primo comando venga eseguito in una funzione shell ...

Quindi questo 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))
$

esegue il printf "%3d: " "$LINENO"comando prima di ogni comando nello script e produce questo output:

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

Appunti:

  • Come la risposta di l0b0 , questa è minimamente invasiva - basta aggiungere la riga 2.
  • A differenza della risposta di l0b0 , questo non mostra i comandi stessi, ma non hai chiesto di farlo.
  • Il secondo sleep, che si estende sulle righe di script 6 e 7, è riportato come riga 7.
  • La riga 11 ( for f in *) viene riportata una volta prima di ogni iterazione di quel forciclo.
  • echo "$f"e ls -ld "$f"sono riportati correttamente sulle rispettive righe (13 e 14).
  • La riga 17 ( for ((i=0; i<3; i++))) viene riportata due volte prima di ogni iterazione di quel forloop e due volte più dopo l'ultima iterazione.
  • A differenza di set -x, LINENOe PS4 (che sono specificati dallo standard POSIX), DEBUG trapè un'estensione bash e non funzionerà in tutte le shell.
  • DEBUG trappuò eseguire qualsiasi comando (i) e non si limita a scrivere nell'output standard dello script o in un errore standard.

La domanda dice: «controlla quale numero di riga di uno script bash viene eseguito“ proprio ora ”» senza specificare un'interfaccia utente. Un altro approccio è quello di scrivere continuamente il numero di riga corrente in un file di registro:

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

Possiamo monitorare l'esecuzione di questo script monitorando il contenuto del myscript2.logfile da un altro terminale. Ad esempio, durante il secondo sleep,

$ tail myscript2.log
  3
  4
  5
  7

6

È possibile echo $LINENOin uno script che dovrebbe generare qualsiasi riga su cui si trovi il comando.

#!/bin/bash
echo $LINENO

$ ./foo.sh
2

-1
#!/bin/bash -x

Aggiungi quella "-x" all'inizio del tuo script. Quindi, ogni volta che esegui lo script, viene ripetuta la riga che esegue lo script. come un albero di esecuzione della tua sceneggiatura.


4
Il PO ha già respinto questo suggerimento come insoddisfacente.
G-Man dice "Ripristina Monica" il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.