Як налагодити скрипт bash? [зачинено]


159

Чи є спосіб налагодити скрипт bash? Наприклад, щось, що друкує такий собі журнал виконання, як "виклик рядка 1", "лінія виклику 2" тощо.



Відповіді:


195
sh -x script [arg1 ...]
bash -x script [arg1 ...]

Вони дають вам слід про те, що виконується. (Див. Також "Роз'яснення" внизу відповіді.)

Іноді вам потрібно контролювати налагодження в сценарії. У такому випадку, як нагадав мені Cheeto , ви можете використовувати:

set -x

Це вмикає налагодження. Потім ви можете вимкнути його знову за допомогою:

set +x

(Ви можете дізнатися поточний стан відстеження, проаналізувавши $-поточні прапори для x.)

Також оболонки, як правило, надають параметри " -n" для "без виконання" та -v"для" багатослівного "режиму; Ви можете використовувати їх у поєднанні, щоб побачити, чи думає оболонка, що вона може виконати ваш сценарій - іноді корисно, якщо десь є незбалансована цитата


Існує думка, що -xваріант ' ' у Bash відрізняється від інших оболонок (див. Коментарі). Керівництво Bash каже:

  • Роздрукуйте слід простих команд, forкоманд, caseкоманд, selectкоманд та арифметичних forкоманд та їхніх аргументів або пов'язаних списків слів після їх розширення та перед їх виконанням. Значення PS4змінної розширюється, а отримане значення друкується перед командою та її розширеними аргументами.

Це, здається, зовсім не свідчить про різну поведінку. Я не бачу жодних інших відповідних посилань на " -x" в посібнику. Він не описує відмінності в послідовності запуску.

Пояснення : У таких системах, як типовий Linux-скриньку, де ' /bin/sh' є символьним посиланням на ' /bin/bash' (або де б не було знайдено виконуваний файл Bash), два командні рядки досягають еквівалентного ефекту від запуску скрипта із слідом виконання. В інших системах (наприклад, Solaris і деяких більш сучасних варіантах Linux) /bin/shне є Bash, і два командні рядки дали б (трохи) різні результати. Найголовніше, що ' /bin/sh' плутатимуть конструкції в Баші, які він зовсім не визнає. (На Solaris /bin/sh- оболонка Bourne; в сучасному Linux це іноді Dash - менша, більш строга оболонка, призначена лише для POSIX.) Коли викликається така назва, рядок 'shebang' (' #!/bin/bash' vs '#!/bin/sh'

У посібнику Bash є розділ про режим Bash POSIX, який, всупереч давній, але помилковій версії цієї відповіді (див. Також коментарі нижче), докладно описує різницю між "Bash посилається як sh" і "Bash викликається як bash'.

Під час налагодження сценарію оболонки (Bash) обов`язково і розумно - навіть необхідно - використовувати оболонку, названу в рядку shebang, за допомогою -xпараметра. В іншому випадку ви можете (будете?) Отримувати іншу поведінку під час налагодження від виконання сценарію.


1
Він точно вказав bashсценарій. І запуск bash-скрипту з ним sh -xпризведе до того, що він поводиться зовсім інакше! Будь ласка, оновіть свою відповідь.
lhunath

1
@lhunath: Яким чином 'sh -x' (або 'bash -x') змушує сценарій поводитися зовсім інакше? Очевидно, він виводить інформацію про сліди в більш жорсткий; це дано (хоча в моїй відповіді не згадується). Але що ще? Я використовую "bash" як "sh" для Linux та MacOS X, і не помітив серйозної проблеми.
Джонатан Леффлер

6
Існують відмінності як при запуску, так і під час виконання. Вони повністю задокументовані в дистрибуції Bash.
TheBonsai

4
Ось посилання на bash doc: gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files 'Якщо Bash викликається іменем sh, він намагається імітувати поведінку при запуску історичних версій sh as наскільки це можливо, в той час як в відповідності зі стандартом POSIX , як добре »
thethinman

6
І скористайтеся підказок PS4, щоб дати більше корисної інформації, наприклад:export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
estani

28

Я використовував наступні методи для налагодження мого сценарію.

set -eзмушує сценарій негайно зупинятися, якщо будь-яка зовнішня програма повертає ненульовий статус виходу. Це корисно, якщо ваш скрипт намагається обробити всі випадки помилок, і якщо невдача цього повинна бути захоплена.

set -x Згадано вище і, безумовно, є найбільш корисним з усіх методів налагодження.

set -n може бути корисним, якщо ви хочете перевірити свій скрипт на наявність синтаксичних помилок.

straceтакож корисно подивитися, що відбувається. Особливо корисно, якщо ви самі не написали сценарій.


1
Розшифровка сценарію (тобто розшарування оболонки, що виконує сценарій) - це дивний спосіб налагодження оболонки (але може працювати для обмеженого набору питань).
TheBonsai

1
Я визнаю, це дивно, а також дуже багатослівно, але якщо обмежити вихід страйсу декількома систематичними викликами, це стане корисним.

1
Зауважте, що strace -fце потрібно, якщо ви також хочете знайти помилки в процесах, запущених сценарієм. (що робить його в багато разів більш багатослівним, але все ж корисним, якщо ви обмежите його на системні дзвінки, які вас цікавлять).
Випадково832


12

Ця відповідь є дійсною та корисною: https://stackoverflow.com/a/951352

Але я вважаю, що "стандартні" методи налагодження сценарію неефективні, неінтуїтивні та важкі у використанні. Для тих, хто звик до складних налагоджувачів графічного інтерфейсу, які ставлять усе під рукою і роблять роботу легким для легких проблем (і можливих для важких проблем), ці рішення не дуже задовільні.

Що я роблю, це використовувати комбінацію DDD та bashdb. Перший виконує останній, а останній виконує ваш сценарій. Це забезпечує багатовіконний інтерфейс з можливістю переходити до коду в контексті та переглядати змінні, стеки тощо, без постійних розумових зусиль, щоб підтримувати контекст у вашій голові або продовжувати повторне перерахування джерела.

Тут є вказівки щодо налаштування цього веб-сайту: http://ubuntuforums.org/showthread.php?t=660223


Щойно виявив ddd завдяки вашій відповіді. У Ubuntu 12.04.3 (64bit) версія apt-джерел не працює. Мені довелося компілювати та встановлювати з джерела, щоб почати налагодження мого скрипту bash. Тут допомогли інструкції - askubuntu.com/questions/156906/… .
хронодекар

Так, це проблема. Я вирішив це деякий час назад з деякими сценаріями - «» dddbash Установки / будує DDD, видаляє стару версія , якщо її неправильно, встановлює bashdb і т.д. (відповідь був відредагований з цією інформацією в даний час)
Stabledog


10

Я знайшов утиліту shellcheck і, можливо, хтось вважає це цікавим https://github.com/koalaman/shellcheck

Маленький приклад:

$ cat test.sh 
ARRAY=("hello there" world)

for x in $ARRAY; do
  echo $x
done

$ shellcheck test.sh 

In test.sh line 3:
for x in $ARRAY; do
         ^-- SC2128: Expanding an array without an index only gives the first element.

виправте помилку, спершу спробуйте ...

$ cat test.sh       
ARRAY=("hello there" world)

for x in ${ARRAY[@]}; do
  echo $x
done

$ shellcheck test.sh

In test.sh line 3:
for x in ${ARRAY[@]}; do
         ^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.

Спробуємо ще раз ...

$ cat test.sh 
ARRAY=("hello there" world)

for x in "${ARRAY[@]}"; do
  echo $x
done

$ shellcheck test.sh

знайдіть зараз!

Це лише невеликий приклад.



На щастя, інструмент розвинувся до того моменту, коли він також знайде решту помилок.
tripleee

3

Встановіть VSCode , потім додайте розширення налагодження bash, і ви готові налагоджувати у візуальному режимі. дивіться Тут у дії.

введіть тут опис зображення


3

Скористайтеся затемненням із вбудованими плагінами та вбраннями.

https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory

Для обстрілу: завантажте zip та імпортуйте його у затемнення за допомогою довідки -> встановіть нове програмне забезпечення: локальний архів Для basheclipse: Скопіюйте банки в каталог крапель затемнення

Виконайте вказівки https://sourceforge.net/projects/basheclipse/files/?source=navbar

введіть тут опис зображення

Я написав підручник з багатьма скріншотами на http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html


2
Це відповідь лише для прикордонних посилань (також дивіться тут ). Ви повинні розширити свою відповідь, щоб включити сюди якомога більше інформації, принаймні мінімум, необхідний для того, щоб реально виконати те, що ви пропонуєте, і використовувати посилання лише для довідки. По суті, публікації на Переповнення стека (і всі Stack Exchange) повинні бути самостійними. Це означає, що у вашій відповіді повинно бути достатньо інформації, щоб читачеві не потрібно було виходити за межі сайту за вказівками. Зараз це не так для цієї відповіді.
Макіен

це перша відповідь, яку я знайшов після перегляду багатьох, що насправді показує, що справжня налагодження можлива. Стандартні відповіді "set + x" чудово відповідають самодостатній відповіді, але майже самовільно ігнорують справжні запитання щодо справжньої налагодження. Я аплодую цю відповідь 👏
simbo1905

2

Я побудував налагоджувач Bash. Просто спробуйте. Сподіваюся, це допоможе https://sourceforge.net/projects/bashdebugingbash


В даний час BDB підтримується англійською та іспанською мовами. Щоб змінити мову, відредагуйте файл / etc / default / bdb
abadjm

знімок екрана виглядає цікаво, але я не міг змусити його запускати "bdb.sh: рядок 32: bdbSTR [1]: незв'язна змінна"; btw покаже це поточні значення всіх заданих змінних кожен крок, який ми робимо в коді?
Сила Водолія

2

встановити + x = @ECHO OFF, встановити -x = @ECHO ON.


Ви можете додати -xvваріант до стандартного Shebang наступним чином:

#!/bin/bash -xv  

-x: Відображення команд та їх аргументів під час їх виконання.
-v: Відображення ліній введення оболонки під час їх зчитування.


ltrace- це ще одна утиліта Linux, схожа на strace. Однак ltraceперелічені всі дзвінки бібліотеки, що викликаються у виконаному або запущеному процесі. Сама назва походить від трасування викликів бібліотеки. Наприклад:

ltrace ./executable <parameters>  
ltrace -p <PID>  

Джерело


1

Я думаю, ви можете спробувати цей відладчик Bash: http://bashdb.sourceforge.net/ .


Існує велика кількість деталей щодо реєстрації скриптів оболонки за допомогою глобальних змінних оболонок. Ми можемо наслідувати подібний тип входу в сценарій оболонки: cubicrace.com/2016/03/efficient-logging-mechnism-in-shell.html
Piyush Chordia

1

Якась хитрість налагодження сценарії:

Використання set -[nvx]

Окрім

set -x

і

set +x

для зупинки звалища.

Я хотів би поговорити про те, set -vщо звалище має менший розмір та менш розвинену продукцію.

bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21

for arg in x v n nx nv nvx;do echo "- opts: $arg"
    bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
        set -$arg
        for i in {0..9};do
            echo $i
          done
        set +$arg
        echo Done.
eof
    sleep .02
  done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5

Дамп змінні або трасування на льоту

Для тестування деяких змінних я використовую колись це:

bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args

для додавання:

declare >&2 -p var1 var2

у рядку 18 та запущений результуючий скрипт (з аргументами ), не потребуючи їх редагування.

Звичайно, це можна використати для додавання set [+-][nvx]:

bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args

буде додано declare -p v1 v2 >&2після рядка 18, set -xперед рядком 22 та set +xперед рядком 26.

маленький зразок:

bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
        seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8

Примітка: на піклування про $LINENOце впливатимуть модифікації, які будуть на ходу !

(Щоб побачити отриманий скрипт без виконання, просто опустіть bash <(і ) arg1 arg2)

Крок за кроком, час виконання

Погляньте на мою відповідь про те, як профілювати bash-скрипти


0

Існує велика кількість деталей щодо реєстрації скриптів оболонки за допомогою глобальних змінних оболонок. Ми можемо наслідувати подібний тип входу в сценарій оболонки: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html

У публікації є детальна інформація про вхідні рівні журналів, такі як INFO, DEBUG, ERROR. Деталі відстеження, такі як запис сценарію, вихід сценарію, введення функції, вихід функції.

Приклад журналу:

введіть тут опис зображення

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