Як перевірити, який рядок скрипта bash виконується

Чи можна перевірити, який рядок номер скрипта bash виконується "прямо зараз"?

14
bash -x script.sh
додано Автор roaima, джерело
@roaima виглядає багатообіцяючим, проте мені потрібно отримати поточний номер рядка
додано Автор Dshead, джерело

5 Відповіді

Об'єднати < код> xtrace за допомогою PS4 усередині сценарію:

$ 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

або у батьківській оболонці :

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

Так, є спосіб.
Існує масив номерів рядків, у яких викликана функція.

Визначте цю функцію:

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

І зателефонуйте f у будь-який рядок, у якому потрібно вказати номер рядка, наприклад:

#!/bin/bash


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

f

echo next1
f

echo next2
f

echo next 3
f

Друкується:

6
next 1
9
next 2
12
next 3
15

Він може бути розширений, щоб показати слід функцій:

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

Which Друкується:

$ ./script
  7
next 1
    This line numbering:    7
test the line numbering:     7
next 2
    This line numbering:    7
test the line numbering:     7
next 3
    This line numbering:    7

Note that above the echo "$LINENO" output is always the same (7 in this case).

10
додано

Ось рішення що запозичує частину l0b0 Відповіді "# 355971"> DopeGhoti (і, у меншій мірі, sorontar ). Як і ті відповіді, шахта використовує $ LINENO для виявлення номера рядка; на відміну від них, я використовую trap для запуску звітів. Команда trap bash's описана в bash ) :

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

    The command arg is to be read and executed when the shell receives signal(s) sigspec.  … ⁠     ︙
    …  If a sigspec is DEBUG, the command arg is executed before every simple command, for command, case command, select command, every arithmetic for command, and before the first command executes in a shell function …

Отже, цей сценарій:

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

запускає команду printf "% 3d:" "$ LINENO" перед кожною командою скрипту і видає цей вивід:

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

Примітки:

  • Like l0b0’s answer, this is minimally invasive — just add line 2.
  • Unlike l0b0’s answer, this doesn’t display the commands themselves — but you didn’t ask for it to do that.
  • The second sleep, which spans script lines 6 and 7, is reported as line 7.
  • Line 11 (for f in *) is reported once before each iteration of that for loop.
  • echo "$f" and ls -ld "$f" are correctly reported on their respective lines (13 and 14).
  • Line 17 (for ((i=0; i<3; i++))) is reported twice before each iteration of that for loop, and twice more after the last iteration.
  • Unlike set -x, LINENO and PS4 (which are specified by the POSIX standard), the DEBUG trap is a bash extension and will not work in all shells.
  • The DEBUG trap can run any command(s), and is not restricted to writing to the script’s standard output or standard error.

Питання говорить: «перевірте номер рядка баш-скрипта виконується “прямо зараз” »без вказівки інтерфейсу користувача. Інший підхід полягає в тому, щоб постійно записувати поточний номер рядка до файлу журналу:

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

Ми можемо стежити за виконанням цього сценарію шляхом контролю вмісту файлу myscript2.log з іншого терміналу. Наприклад, під час другого sleep ,

$ tail myscript2.log
  3
  4
  5
  7
6
додано

Ви можете echo $ LINENO у скрипті, і вона повинна виводити будь-яку лінію, на якій відбувається команда.

#!/bin/bash
echo $LINENO

$ ./foo.sh
2
6
додано
#!/bin/bash -x

Додайте, що "-x" на початку вашого сценарію. Потім кожен раз, коли ви виконуєте скрипт, він відтворює рядок, який виконує ваш скрипт. як дерево виконання вашого сценарію.

1
додано
Оперативна програма вже відхилила цю пропозицію як незадовільну.
додано Автор G-Man, джерело