Как отладить скрипт 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' будет смущен конструкциями в Bash, которые он вообще не распознает. (В 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приведет к тому, что он будет вести себя совершенно иначе! Пожалуйста, обновите свой ответ.
— 1

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

6
Есть различия, при запуске и во время выполнения. Они полностью документированы в дистрибутиве Bash.
— TheBonsai

4
Вот ссылка на документ bash: gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files 'Если Bash вызывается с именем sh, он пытается имитировать поведение при запуске исторических версий sh как настолько близко, насколько это возможно, и в то же время соответствует стандарту 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
Я признаю, что это странно и очень многословно, но если вы ограничите вывод strace несколькими системными вызовами, это станет полезным.

1
Обратите внимание, что strace -fэто необходимо, если вы также хотите найти ошибки в процессах, запускаемых скриптом. (что делает его во много раз более многословным, но все же полезно, если вы ограничите его системными вызовами, которые вас интересуют).
— Random832

set -eявляется ... спорным .
— Чарльз Даффи

12

Этот ответ действителен и полезен: https://stackoverflow.com/a/951352

Но я считаю, что «стандартные» методы отладки скриптов неэффективны, не интуитивно понятны и сложны в использовании. Для тех, кто привык к сложным отладчикам с графическим интерфейсом, которые держат все под рукой и делают работу проще для простых проблем (и возможно для сложных проблем), эти решения не очень удовлетворительны.

Я использую комбинацию DDD и bashdb. Первый выполняет последний, а второй выполняет ваш сценарий. Это обеспечивает многооконный интерфейс с возможностью пошагового просмотра кода в контексте и просмотра переменных, стека и т. Д. Без постоянных умственных усилий для сохранения контекста в вашей голове или повторного перечисления источника.

Руководство по его настройке приведено здесь: http://ubuntuforums.org/showthread.php?t=660223


Только что обнаружил DDD благодаря вашему ответу. В Ubuntu 12.04.3 (64bit) версия apt-sources не работает. Мне пришлось скомпилировать и установить из исходного кода, чтобы начать отладку моего 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

Используйте Eclipse с плагинами и панцирями.

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

Для шелуша: загрузите zip и импортируйте его в eclipse с помощью справки -> установите новое программное обеспечение: локальный архив Для basheclipse: скопируйте jar-файлы в директорию dropins eclipse

Следуйте инструкциям на https://sourceforge.net/projects/basheclipse/files/?source=navbar

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

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


2
Это только пограничный ответ (см. Также здесь ). Вы должны расширить свой ответ, включив в него как можно больше информации, по крайней мере, минимум, необходимый для того, чтобы действительно выполнить то, что вы предлагаете, и использовать ссылки только для справки. По сути, сообщения о переполнении стека (и все в стеке обмена) должны быть автономными. Это означает, что в вашем ответе должно быть достаточно информации, чтобы читателю не нужно было уходить за пределы сайта для получения указаний. Прямо сейчас, это не тот случай для этого ответа.
— Макьен

это первый ответ, который я нашел после просмотра многих, который фактически показывает, что настоящая отладка возможна. Стандартные ответы «set + x» идеально соответствуют самодостаточному ответу, но почти намеренно игнорируют истинные вопросы об истинной отладке. Я приветствую этот ответ 👏
— simbo1905

2

Я построил отладчик Bash. Просто попробуйте. Я надеюсь, что это поможет https://sourceforge.net/projects/bashdebugingbash


BDB в настоящее время поддерживается на английском и испанском языках. Чтобы изменить язык, отредактируйте файл / etc / default /
— bdb

скриншот выглядит интересно, но я не могу заставить его работать "bdb.sh: строка 32: bdbSTR [1]: несвязанная переменная"; Кстати, он будет показывать текущие значения всех установленных переменных каждый шаг, который мы делаем в коде?
— Водолей Сила

2

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


Вы можете добавить -xvопцию к стандартному Шебангу следующим образом:

#!/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.