Як показати номер рядка під час виконання скрипта bash


89

У мене є тестовий скрипт, який має багато команд і буде генерувати багато результатів, я використовую set -xабо set -vі set -e, тому скрипт зупиняється, коли виникає помилка. Однак мені все ще досить важко визначити, який рядок зупинив виконання, щоб знайти проблему. Чи існує метод, який може вивести номер рядка сценарію перед виконанням кожного рядка? Або вивести номер рядка перед виставкою команд, згенерованою set -x? Або будь-який метод, який може впоратися з моєю проблемою розташування рядка сценарію, буде чудовою підмогою. Дякую.

Відповіді:


160

Ви згадуєте, що вже використовуєте -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
Чоловіче, хотілося б, щоб я швидше дізнався про цю суміш PS4 ... Це б врятувало мені стільки головних болів
niken

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 для користувачів золи або інших оболонок без LINENO.

Ще щось додати?

Звичайно. Навіщо вам це? Як ви працюєте з цим? Що ви можете з цим зробити? Цей простий підхід насправді достатній чи корисний? Чому ти взагалі хочеш з цим повозитися?

Хочете знати більше? Прочитайте роздуми про налагодження

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.