So überprüfen Sie, welche Zeile eines Bash-Skripts ausgeführt wird

15

Gibt es eine Möglichkeit , die Leitung zu überprüfen Nummer eines bashSkript wird „right now“ ausgeführt?

Verwenden bash -x script.shsieht vielversprechend aus; Ich muss jedoch die aktuelle Zeilennummer abrufen.

user224371
quelle

Antworten:

20

Kombiniere xtracemit PS4im Skript:

$ 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

oder in der übergeordneten Shell :

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

Ja, es gibt einen Weg.
Es gibt ein Array von Zeilennummern, in denen eine Funktion aufgerufen wurde.

Definieren Sie diese Funktion:

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

Und rufen Sie fan jeder beliebigen Leitung an, an der Sie die Leitungsnummer haben möchten, zum Beispiel:

#!/bin/bash


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

f

echo next1
f

echo next2
f

echo next 3
f

Druckt:

6
next 1
9
next 2
12
next 3
15

Es könnte erweitert werden, um die Funktionsspur anzuzeigen, die aufgerufen wird:

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

Welches wird drucken:

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

Beachten Sie, dass die echo "$LINENO"Ausgabe oben immer dieselbe ist (in diesem Fall 7).

Sorontar
quelle
6

Sie können echo $LINENOin einem Skript eine beliebige Zeile ausgeben, in der sich der Befehl gerade befindet.

#!/bin/bash
echo $LINENO

$ ./foo.sh
2
DopeGhoti
quelle
6

Hier ist eine Lösung, die Teile der Antworten von l0b0 und DopeGhoti (und in geringerem Maße von sorontar ) übernimmt . Wie diese Antworten verwendet Mine $LINENO, um die Zeilennummer zu ermitteln. im gegensatz zu ihnen starte ich trapdie berichterstattung mit. Der trapBefehl von bash wird in bash (1) beschrieben :

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

    Der Befehl arg soll gelesen und ausgeführt werden, wenn die Shell das Signal sigspec empfängt . ... ⁠ ︙
    ... Wenn ein sigspec ist DEBUG , der Befehl arg wird vor jedem Ausführung einfachen Befehl , forBefehl, caseBefehl, selectBefehl, jeden arithmetischen forBefehl und vor dem ersten Befehl ausgeführt wird in einer Shell - Funktion ...

Also dieses Skript:

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

Führt den printf "%3d: " "$LINENO"Befehl vor jedem Befehl im Skript aus und gibt Folgendes aus:

$ ./myscript
  3: Mi, 5. April 2017, 10:16:17 Uhr
  4: 5: Mi, 05.04.2017, 10:16:47 Uhr
  7: 8: Mi, 5. April 2017, 10:16:58 Uhr
 10: insgesamt 4
-rwxr-xr-x 1 meinbenutzername meinegruppe 221 5. april 10:01 myscript
-rwxr-xr-x 1 meinbenutzername meinegruppe 252 5. april 10:01 myscript2
-rw-r - r-- 1 meinbenutzername meinegruppe 132 5. april 09:59 myscript2.log
-rw-r - r-- 1 meinbenutzername meinegruppe   45 Apr 5 08:34 other_file
 11: 13: myscript
 14: -rwxr-xr-x 1 meinbenutzername meinegruppe 221 5. april 10:01 myscript
 11: 13: myscript2
 14: -rwxr-xr-x 1 meinbenutzername meinegruppe 252 5. april 10:01 myscript2
 11: 13: myscript2.log
 14: -rw-r - r-- 1 meinbenutzername meinegruppe 132 5. april 09:59 myscript2.log
 11: 13: other_file
 14: -rw-r - r-- 1 meinbenutzername meinegruppe   45 Apr 5 08:34 other_file
 17: 17: 19: i = 0
 19: Mi, 5. April 2017, 10:16:59 Uhr
 17: 17: 19: i = 1
 19: Mi, 5. April 2017, 10:16:59 Uhr
 17: 17: 19: i = 2
 19: Mi, 5. April 2017, 10:16:59 Uhr
 17: 17: 22: 42
$

Anmerkungen:

  • Wie die Antwort von l0b0 ist dies minimal invasiv - fügen Sie einfach Zeile 2 hinzu.
  • Im Gegensatz zur Antwort von l0b0 werden hier die Befehle nicht angezeigt - aber Sie haben nicht darum gebeten .
  • Die zweite sleepZeile, die sich über die Skriptzeilen 6 und 7 erstreckt, wird als Zeile 7 gemeldet.
  • Zeile 11 ( for f in *) wird einmal vor jeder Iteration dieser forSchleife gemeldet .
  • echo "$f"und ls -ld "$f"werden in ihren jeweiligen Zeilen (13 und 14) korrekt gemeldet.
  • Zeile 17 ( for ((i=0; i<3; i++))) wird zweimal vor jeder Iteration dieser forSchleife und zweimal nach der letzten Iteration gemeldet .
  • Im Gegensatz zu set -x, LINENOund PS4 (die durch den POSIX - Standard spezifiziert ist), die DEBUG trapist eine Erweiterung bash und wird nicht funktionieren in allen Schalen.
  • Der DEBUG trapkann alle Befehle ausführen und ist nicht auf das Schreiben in die Standardausgabe oder den Standardfehler des Skripts beschränkt.

Die Frage lautet: "Überprüfen Sie, welche Zeilennummer eines Bash-Skripts gerade ausgeführt wird", ohne eine Benutzeroberfläche anzugeben. Ein anderer Ansatz besteht darin, die aktuelle Zeilennummer kontinuierlich in eine Protokolldatei zu schreiben:

$ diff myscript myscript2
2c2
<trap 'printf "% 3d:" "$ LINENO"' DEBUG
---
> exec 6> myscript2.log && trap 'printf "% 3d \ n" "$ LINENO"> & 6' DEBUG
$ ./myscript2
Mittwoch, 5. April 2017, 10:23:50 Uhr
Mittwoch, 5. April 2017, 10:24:20 Uhr
Mittwoch, 5. April 2017, 10:24:31 Uhr
insgesamt 4
-rwxr-xr-x 1 meinbenutzername meinegruppe 221 5. april 10:01 myscript
-rwxr-xr-x 1 meinbenutzername meinegruppe 252 5. april 10:01 myscript2
-rw-r - r-- 1 meinbenutzername meinegruppe   24 Apr 5 10:23 myscript2.log
-rw-r - r-- 1 meinbenutzername meinegruppe   45 Apr 5 08:34 other_file
myscript
-rwxr-xr-x 1 meinbenutzername meinegruppe 221 5. april 10:01 myscript
myscript2
-rwxr-xr-x 1 meinbenutzername meinegruppe 252 5. april 10:01 myscript2
myscript2.log
-rw-r - r-- 1 meinbenutzername meinegruppe   60 Apr 5 10:23 myscript2.log
other_file
-rw-r - r-- 1 meinbenutzername meinegruppe   45 Apr 5 08:34 other_file
i = 0
Mittwoch, 5. April 2017, 10:24:31 Uhr
i = 1
Mittwoch, 5. April 2017, 10:24:31 Uhr
i = 2
Mittwoch, 5. April 2017, 10:24:31 Uhr
42
$

Wir können die Ausführung dieses Skripts überwachen, indem wir den Inhalt der myscript2.logDatei von einem anderen Terminal aus überwachen . Zum Beispiel während der zweiten sleep,

$ tail myscript2.log
  3
  4
  5
  7
G-Man sagt, "Monica wiedereinsetzen"
quelle
-1
#!/bin/bash -x

Fügen Sie das "-x" am Anfang Ihres Skripts hinzu. Jedes Mal, wenn Sie das Skript ausführen, wird die Zeile wiedergegeben, die Ihr Skript ausführt. wie ein Ausführungsbaum Ihres Skripts.

Pavan Shah
quelle
4
Das OP hat diesen Vorschlag bereits als unbefriedigend abgewiesen.
G-Man sagt, dass Monica am