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


89

У меня есть тестовый скрипт, который имеет множество команд и будет генерировать много вывода, я использую set -xили set -vи set -e, поэтому скрипт остановится при возникновении ошибки. Однако мне все еще довольно сложно определить, в какой строке остановилось выполнение, чтобы найти проблему. Есть ли метод, который может выводить номер строки скрипта перед выполнением каждой строки? Или выведите номер строки перед выставкой команды, сгенерированной set -x? Или любой метод, который может решить мою проблему с местоположением строки сценария, будет большим подспорьем. Спасибо.

Ответы:


159

Вы упоминаете, что уже используете -x. Переменная PS4означает, что значение - это приглашение, выводимое перед выводом командной строки, когда -xпараметр установлен, и по умолчанию используется значение, :за которым следует пробел.

Вы можете изменить, PS4чтобы испустить LINENO(номер строки в скрипте или функции оболочки, выполняемой в данный момент).

Например, если ваш сценарий гласит:

$ cat script
foo=10
echo ${foo}
echo $((2 + 2))

При его выполнении будут напечатаны номера строк:

$ PS4='Line ${LINENO}: ' bash -x script
Line 1: foo=10
Line 2: echo 10
10
Line 3: echo 4
4

http://wiki.bash-hackers.org/scripting/debuggingtips дает окончательный результат PS4, который выводит все, что вам может понадобиться для трассировки:

export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'

4
Интересно, почему никто не упоминает об этом в разделе «Как отлаживать сценарии оболочки?» . Это намного лучше, чем простоecho
Суварна Паттайил

@VusP Согласен, ненужных echoзаявлений лучше избегать.
devnull

2
Я не могу не чувствовать, что -x должны печатать номера строк. Или, может быть - nx должен включать номера строк. Для меня это один из тех моментов "WTF" ...
jww

1
Чувак, я хотел бы
узнать об этой

2
\033[0;33m+(${BASH_SOURCE}:${LINENO}):\033[0m ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'для некоторых цветов
Ulysse BN

34

В Bash $LINENOсодержит номер строки, в которой в данный момент выполняется скрипт.

Если вам нужно узнать номер строки, в которой была вызвана функция, попробуйте $BASH_LINENO. Обратите внимание, что эта переменная представляет собой массив.

Например:

#!/bin/bash       

function log() {
    echo "LINENO: ${LINENO}"
    echo "BASH_LINENO: ${BASH_LINENO[*]}"
}

function foo() {
    log "$@"
}

foo "$@"

Подробнее о переменных Bash см. Здесь .


0

Простое (но мощное) решение: поместите echoвокруг кода, который, по вашему мнению, вызывает проблему, и перемещайте echoпострочно, пока сообщения не перестанут появляться на экране, потому что скрипт остановился из-за предыдущей ошибки.

Еще более мощное решение: установите bashdbотладчик bash и построчно отлаживайте скрипт.


2
echoВо многих случаях это может помочь, но терпит неудачу, когда вы пытаетесь применить его в функциях, которые имеют осмысленный, анализируемый вывод.
Элиран Малка

1
@EliranMalka Ярмарка. В этом случае вы можете повторить эхо на stderr:echo "foo" >&2
hek2mgl

1
... нужно выводить на stderr эхо во всех случаях, когда цель - сообщения диагностического характера.
Чарльз Даффи,

0

Обходной путь для оболочек без LINENO

В довольно сложном сценарии я не хотел бы видеть все номера строк; скорее я хотел бы контролировать выход.

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

echo_line_no () {
    grep -n "$1" $0 |  sed "s/echo_line_no//" 
    # grep the line(s) containing input $1 with line numbers
    # replace the function name with nothing 
} # echo_line_no

Используйте его с кавычками вроде

echo_line_no "this is a simple comment with a line number"

Выход

16   "this is a simple comment with a line number"

если номер этой строки в исходном файле равен 16.

Это в основном отвечает на вопрос, как показать номер строки при выполнении сценария bash для пользователей ash или других оболочек без LINENO.

Есть что еще добавить?

Конечно. зачем вам это? Как с этим работать? Что с этим делать? Действительно ли этого простого подхода достаточно или полезно? Почему вы вообще хотите с этим повозиться?

Хотите узнать больше? Прочтите размышления по отладке

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.