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

-e предназначен для случаев, когда вам нужна удаленная оболочка отличная от стандартной ssh. rsync использует ssh в качестве транспорта по умолчанию, но может использовать любую удаленную оболочку (с парой ограничений*), ему не важно, как он подключается к удаленному серверу.

* Удаленная оболочка, которую вы используете, должна вести себя как оболочка. Она должна интерпретировать свой нулевой аргумент как место назначения, а каждый следующий аргумент как команду для выполнения; команда, которую rsync передает удаленной оболочке, это команда rsync --server ..., которая запускает сервер rsync на удаленном конце. Он также должен присоединить свой STDIN к STDIN команды, а STDOUT команды к STDOUT, чтобы rsync и сервер rsync могли общаться через удаленный shell.

15
25.07.2019, 22:22
5 ответов

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

#!/bin/bash
echo $LINENO

$ ./foo.sh
2
6
27.01.2020, 19:49
#!/bin/bash -x

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

-1
27.01.2020, 19:49

Объединить 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
21
27.01.2020, 19:49

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

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

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 в данном случае).

10
27.01.2020, 19:49

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

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

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

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

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

Примечания:

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

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

$ 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 с другого терминала. Например, во время второго сна,

$ tail myscript2.log
  3
  4
  5
  7
7
27.01.2020, 19:49

Теги

Похожие вопросы