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

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

  • Как извлечь и объединить значения переменных в другую переменную?
  • Как удалить имя из фамилии, когда длина неизвестна?
  • Как вернуть 0, если шаблон сопоставлен с файлом?
  • zsh HISTFILE - все еще читается из ~ / .zsh_history
  • Как я запускаю сценарий n раз в одно и то же время и как имитировать семафор?
  • Найти и переименовать файлы, добавляющие часть пути к имени файла
  • Как удалить каталог символьных ссылок ссылки плюс символическая ссылка?
  • Сценарий интерпретатора сценариев CentOS 7
  • 5 Solutions collect form web for “Как проверить, какая строка скрипта bash выполняется”

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

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

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

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

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

     #!/bin/bash echo $LINENO $ ./foo.sh 2 

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

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

      Команда arg должна считываться и выполняться, когда оболочка получает сигнал (ы) sigspec . … ⁠ ︙
      … Если sigspec является DEBUG , команда arg выполняется перед каждой простой командой , командой command, case command, командой 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: Wed, Apr 05, 2017 10:16:17 AM
       4: 5: ср., Апрель 05, 2017 10:16:47
       7: 8: ср., Апрель 05, 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: other_file
      14: -rw-r - r-- 1 myusername mygroup 45 Апр 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 , это не отображает сами команды, но вы не просили об этом.
    • Второй sleep , который охватывает строки сценариев 6 и 7, сообщается как строка 7.
    • Строка 11 ( for f in * ) сообщается раз перед каждой итерацией этого цикла.
    • echo "$f" и ls -ld "$f" корректно отображаются в соответствующих строках (13 и 14).
    • Строка 17 ( for ((i=0; i<3; i++)) ) сообщается дважды перед каждой итерацией цикла for и еще дважды после последней итерации.
    • В отличие от set -x , LINENO и PS4 (которые указаны стандартом POSIX), trap DEBUG является расширением bash и не будет работать во всех оболочках.
    • trap 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
     всего 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
     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 
     #!/bin/bash -x 

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

    Linux и Unix - лучшая ОС в мире.