Как проверить, какая строка скрипта bash выполняется


15

Есть ли способ , чтобы проверить , какую линию номер из bashсценария выполняются «прямо сейчас»?

Использование bash -x script.shвыглядит многообещающе; Тем не менее, мне нужно получить текущий номер строки.

Ответы:


20

Объединить 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

10

Да, есть способ.
Существует массив номеров строк, где была вызвана функция.

Определите эту функцию:

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

Который напечатает:

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

Обратите внимание, что выше echo "$LINENO"выход всегда одинаков (7 в данном случае).


7

Вот решение, которое заимствует части ответов l0b0 и DopeGhoti (и, в меньшей степени, ответов sorontar ). Как и те ответы, мой использует, $LINENOчтобы узнать номер строки; в отличие от них, я использую trapдля запуска отчетности. trapКоманда bash описана в bash (1) :

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

    Команда arg должна быть прочитана и выполнена, когда оболочка получает сигнал sigspec . ... ⁠ ︙
    ... Если sigspec является DEBUG , команда агд выполняется перед каждой простой команды , forкоманды, caseкоманды, selectкоманды, каждой арифметической forкоманды, и перед первым выполнением команды в функции оболочки ...

Итак, этот скрипт:

$ 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: ср, 5 апреля 2017 г. 10:16:17
  4: 5: ср, 5 апреля 2017 г. 10:16:47
  7: 8: ср, 5 апреля 2017 г., 10:16:58
 10: всего 4
-rwxr-xr-x 1 myusername mygroup 221 5 апреля 10:01 myscript
-rwxr-xr-x 1 myusername mygroup 252 5 апреля 10:01 myscript2
-rw-r - r-- 1 myusername mygroup 132 5 апреля 09:59 myscript2.log
-rw-r - r-- 1 myusername mygroup   45 апреля 5 08:34 other_file
 11: 13: myscript
 14: -rwxr-xr-x 1 myusername mygroup 221 5 апреля 10:01 myscript
 11: 13: myscript2
 14: -rwxr-xr-x 1 myusername mygroup 252 5 апреля 10:01 myscript2
 11: 13: myscript2.log
 14: -rw-r - r-- 1 myusername mygroup 132 5 апреля 09:59 myscript2.log
 11: 13: другой_файл
 14: -rw-r - r-- 1 myusername mygroup   45 апр. 5 08:34 other_file
 17: 17: 19: я = 0
 19: ср, 5 апреля 2017 г. 10:16:59
 17: 17: 19: я = 1
 19: ср, 5 апреля 2017 г. 10:16:59
 17: 17: 19: я = 2
 19: ср, 5 апреля 2017 г. 10:16:59
 17: 17: 22: 42
$

Примечания:

  • Как и ответ l0b0 , это минимально инвазивно - просто добавьте строку 2.
  • В отличие от ответа l0b0 , здесь не отображаются сами команды - но вы не просили этого сделать это.
  • Второй sleep, который охватывает строки сценария 6 и 7, сообщается как строка 7.
  • Строка 11 ( for f in *) сообщается один раз перед каждой итерацией этого forцикла.
  • echo "$f"и ls -ld "$f"правильно указаны в соответствующих строках (13 и 14).
  • Строка 17 ( for ((i=0; i<3; i++))) сообщается дважды перед каждой итерацией этого forцикла и еще дважды после последней итерации.
  • В отличие set -x, LINENOи PS4 (которые указаны в стандарте POSIX), то DEBUG trapявляется расширение баш и не будет работать во всех оболочках.
  • DEBUG trapможет выполнять любые команды, и не ограничивается записью в стандартный вывод скрипта или стандартную ошибку.

В вопросе говорится: «проверьте, какой номер строки bash-скрипта выполняется« прямо сейчас »» без указания пользовательского интерфейса. Другой подход заключается в непрерывной записи текущего номера строки в файл журнала:

$ diff myscript myscript2
2c2
<trap 'printf "% 3d:" "$ LINENO"' ОТЛАДКА
---
> exec 6> myscript2.log && trap 'printf "% 3d \ n" "$ LINENO"> & 6' DEBUG
$ ./myscript2
Ср, 05 апреля 2017 10:23:50
Ср, 05 апреля 2017 10:24:20
Ср, 05 апреля 2017 10:24:31
всего 4
-rwxr-xr-x 1 myusername mygroup 221 5 апреля 10:01 myscript
-rwxr-xr-x 1 myusername mygroup 252 5 апреля 10:01 myscript2
-rw-r - r-- 1 myusername mygroup   24 апреля 5 10:23 myscript2.log
-rw-r - r-- 1 myusername mygroup   45 апреля 5 08:34 other_file
MyScript
-rwxr-xr-x 1 myusername mygroup 221 5 апреля 10:01 myscript
myscript2
-rwxr-xr-x 1 myusername mygroup 252 5 апреля 10:01 myscript2
myscript2.log
-rw-r - r-- 1 myusername mygroup   60 апреля 5 10:23 myscript2.log
other_file
-rw-r - r-- 1 myusername mygroup   45 апреля 5 08:34 other_file
я = 0
Ср, 05 апреля 2017 10:24:31
я = 1
Ср, 05 апреля 2017 10:24:31
я = 2
Ср, 05 апреля 2017 10:24:31
42
$

Мы можем контролировать выполнение этого скрипта, отслеживая содержимое myscript2.logфайла с другого терминала. Например, во втором sleep,

$ tail myscript2.log
  3
  4
  5
  7

6

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

#!/bin/bash
echo $LINENO

$ ./foo.sh
2

-1
#!/bin/bash -x

Добавьте этот «-x» в начале вашего скрипта. Затем каждый раз, когда вы выполняете скрипт, он повторяет строку, которую исполняет ваш скрипт. как дерево выполнения вашего скрипта.


4
ФП уже отклонил это предложение как неудовлетворительное.
G-Man говорит: «Восстановите Монику»
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.