Как проверить синтаксис сценария Bash, не запуская его?

Можно ли проверить синтаксис сценария bash без его выполнения?

Используя Perl, я могу запустить perl -c 'script name'. Есть ли эквивалентная команда для сценариев bash?


person Tom Feiner    schedule 05.10.2008    source источник


Ответы (9)


bash -n scriptname

Возможно, очевидное предостережение: это проверяет синтаксис, но не проверяет, пытается ли ваш bash-скрипт выполнить команду, которой нет в вашем пути, например ech hello вместо echo hello.

person andy    schedule 05.10.2008
comment
Спасибо за совет, обязательно воспользуюсь этим. Как ни странно, эта опция не указана на странице руководства bash: S... - person skinp; 05.10.2008
comment
На справочной странице bash в разделе ВСТРОЕННЫЕ КОМАНДЫ ОБОЛОЧКИ / set задокументирован -n, и, как указано в начале справочной страницы, bash интерпретирует все односимвольные параметры, которые делает set. - person ephemient; 06.10.2008
comment
чтобы добавить к (для меня) неочевидному предостережению, он также не поймает ошибку, вызванную отсутствием пробела if ["$var" == "string" ] вместо if [ "$var" == "string" ] - person Brynjar; 05.08.2011
comment
@Brynjar Это потому, что это просто проверка синтаксиса. Открытая скобка — это не синтаксис, это имя функции, которую нужно запустить. type [ говорит [является встроенной оболочкой. В конечном итоге он делегирует программу test, но также ожидает закрывающую скобку. Так что это похоже на if test"$var", что не то, что имел в виду автор, но синтаксически допустимо (скажем, $var имеет значение a, тогда мы увидим bash: testa: команда не найдена). Дело в том, что синтаксически нет пропущенного пробела. - person Joshua Cheek; 20.07.2014
comment
@JoshuaCheek: встроенный [ вызывается только в этом случае, если $var расширяется до пустой строки. Если $var заменяется на непустую строку, [ объединяется с этой строкой и интерпретируется как имя команды (а не функции name) от Bash, и да, это синтаксически допустимо, но, как вы утверждаете, явно не намеренно. Если вы используете [[ вместо [, даже несмотря на то, что [[ является ключевым словом оболочки (а не встроенным), вы получите тот же результат, потому что непреднамеренная конкатенация строк по-прежнему переопределяет распознавание ключевого слова. - person mklement0; 12.06.2015
comment
@JoshuaCheek: Bash все еще проверка синтаксиса здесь: он проверяет синтаксис вызова простой команды: ["$var" является синтаксически допустимой командой- имя выражение; аналогично токены == и "$string" являются допустимыми аргументами команды. (Как правило, встроенная команда [ анализируется с синтаксисом command, тогда как [[ — как ключевое слово оболочки — анализируется по-другому.) Встроенная оболочка [ нет делегировать программе test (внешняя утилита): bash, dash, ksh, zsh все имеют встроенные версии как [, так и test, и они не< /i> вызывать их внешние служебные аналоги. - person mklement0; 12.06.2015
comment
Суть такова: используя только сам Bash, -n будет лучшим выбором, но это не позволит выявить многие ошибки, которые могут совершить новички; чтобы отследить их, используйте shellcheck.net или его интерфейс командной строки, как описано в ответ dvd818. - person mklement0; 12.06.2015
comment
@mklement0 хорошо, спасибо за отличное объяснение! - person Joshua Cheek; 23.06.2015
comment
Еще одно предостережение: не будут учитываться параметры, установленные в скрипте. Например, если вы добавите shopt -s extglob, а затем сделаете foo@(bar|baz)) в case, bash -n увидит это как синтаксическую ошибку (bash -s extglob -n не увидит, но вы никогда не знаете, какая часть скрипта затронута) - person Alois Mahdal; 02.07.2015
comment
@AloisMahdal К сожалению, в общем случае это было бы невозможно исправить, поскольку параметры оболочки могут измениться в середине сценария или даже на основе информации, которая может быть известна только во время выполнения. - person Daniel H; 12.05.2018
comment
Вот документация от man bash: -n Read commands but do not execute them. This may be used to check a shell script for syntax errors. This is ignored by interactive shells. - person wisbucky; 25.03.2019
comment
зависит от версии опции -n или ОС; похоже не работает на osx - person qodeninja; 12.09.2019

Время меняет все. Вот веб-сайт, который обеспечивает онлайн-проверку синтаксиса для сценария оболочки.

Я обнаружил, что это очень мощное средство для обнаружения распространенных ошибок.

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

О ShellCheck

ShellCheck – это инструмент статического анализа и проверки скриптов sh/bash. В основном он сосредоточен на обработке типичных синтаксических ошибок и ловушек начального и среднего уровня, когда оболочка просто выдает загадочное сообщение об ошибке или странное поведение, но также сообщает о нескольких более сложных проблемах, где крайние случаи могут вызвать отложенные сбои.

Исходный код Haskell доступен на GitHub!

person dvd818    schedule 24.10.2013
comment
Отличный совет; в OSX теперь также можно установить интерфейс командной строки shellcheck.net, shellcheck, через Homebrew: brew install shellcheck. - person mklement0; 12.06.2015
comment
Также на debian&friends: apt-get install shellcheck - person that other guy; 31.07.2015
comment
Для Ubuntu Trusty этот пакет должен быть установлен из trusty-backports. - person Peterino; 05.08.2015
comment
Как упоминалось выше, необходима надежная зависимость, и ее можно установить, как показано ниже в Ubuntu 14.04: sudo apt-get -f install, затем: sudo sudo apt-get install shellcheck - person zhihong; 08.12.2016
comment
Это действительно полезно, но использует не парсер Bash, а свой собственный. В большинстве случаев этого достаточно, и он может выявить как синтаксический анализ, так и другие проблемы, но есть по крайней мере один пограничный случай (и, вероятно, другие, которые я не видел), когда он не выполняет синтаксический анализ таким же образом. - person Daniel H; 12.05.2018
comment
Если вы хотите запускать свою программу, только если она прошла проверку оболочки: gitlab.com/es20490446e/shellproof - person Alberto Salvia Novella; 13.02.2021

Я также включаю опцию «u» для каждого сценария bash, который я пишу, чтобы выполнить дополнительную проверку:

set -u 

Это сообщит об использовании неинициализированных переменных, как в следующем скрипте «check_init.sh».

#!/bin/sh
set -u
message=hello
echo $mesage

Запуск скрипта:

$ check_init.sh

Сообщит следующее:

./check_init.sh[4]: сообщение: Параметр не установлен.

Очень полезно ловить опечатки

person Diego Tercero    schedule 23.05.2012
comment
я всегда устанавливаю эти флаги в своих сценариях bash, если они проходят, хорошо идти set -o errexit set -o nounset set -o pipefail - person μολὼν.λαβέ; 10.01.2016
comment
+1 за set -u, хотя на самом деле это не отвечает на вопрос, потому что вам нужно запустить скрипт, чтобы получить сообщение об ошибке. Даже bash -n check_init.sh не показывает это предупреждение - person rubo77; 06.07.2017

sh  -n   script-name 

Запустите это. Если в скрипте есть какие-либо синтаксические ошибки, он возвращает такое же сообщение об ошибке. Если ошибок нет, то выходит без каких-либо сообщений. Вы можете проверить это немедленно, используя echo $?, который безошибочно вернет 0, подтверждающий успешное выполнение.

Это сработало для меня хорошо. Я запускал ОС Linux, Bash Shell.

person Jeevan    schedule 02.02.2011
comment
Хотя это не совсем связано с проверкой синтаксиса bash - использование set -x и set +x для отладки всего скрипта или разделов скрипта весьма полезно. - person GuruM; 01.08.2012
comment
Спасибо за это, не знал, не знал о -n, но я хотел, чтобы @GuruM › sh -x test.sh так как он отображает сгенерированный вывод скрипта - person zzapper; 19.06.2013
comment
да. Я забыл упомянуть, что вы можете сделать следующее В командной строке: 1) bash -x test.sh #это запускает весь скрипт в «режиме отладки» 2) set +x; баш тест.ш; set -x #включить/выключить режим отладки до/после запуска скрипта В скрипте: a) #!/bin/bash -x #добавить 'режим отладки' вверху скрипта b) set +x; код; set -x # добавить 'режим отладки' для любого раздела скрипта - person GuruM; 19.06.2013
comment
sh -n, вероятно, не проверит, является ли сценарий допустимым сценарием Bash. Это может дать ложноотрицательные результаты. sh - это некий вариант оболочки Bourne, который обычно не является Bash. Например, в Ubuntu Linux realpath -e $(command -v sh) дает /bin/dash - person jarno; 04.11.2019

На самом деле я проверяю все сценарии bash в текущем каталоге на наличие синтаксических ошибок БЕЗ запуска их с помощью инструмента find:

Пример:

find . -name '*.sh' -exec bash -n {} \;

Если вы хотите использовать его для одного файла, просто отредактируйте подстановочный знак с именем файла.

person Gerald Hughes    schedule 03.08.2017

пустая команда [двоеточие] также полезна при отладке, чтобы увидеть значение переменной

set -x
for i in {1..10}; do
    let i=i+1
    : i=$i
done
set - 
person mug896    schedule 17.01.2014
comment
он использует расширения параметров - person mug896; 08.05.2017
comment
это работает, потому что set -x показывает каждую строку перед ее выполнением - person rubo77; 06.07.2017

Существует плагин BashSupport для IntelliJ IDEA, который проверяет синтаксис.

person Cengiz    schedule 05.12.2015
comment
Но это не сработает, если ваши файлы не заканчиваются на .sh или другим расширением, связанным со сценариями Bash, как в случае, если вы создаете сценарии с помощью какого-либо инструмента для создания шаблонов, такого как ERB (тогда они заканчиваются на .erb). Пожалуйста, проголосуйте за youtrack.jetbrains.com/issue/IDEA-79574, если хотите. фиксированный! - person Greg Dubicki; 22.09.2016

Если вам нужно указать в переменной допустимость всех файлов в каталоге (перехватчик git pre-commit, сборка скрипта lint), вы можете перехватить вывод stderr команд «sh -n» или «bash -n» (см. ответы) в переменной и иметь "if/else" на основе этого

bashErrLines=$(find bin/ -type f -name '*.sh' -exec sh -n {} \;  2>&1 > /dev/null)
  if [ "$bashErrLines" != "" ]; then 
   # at least one sh file in the bin dir has a syntax error
   echo $bashErrLines; 
   exit; 
  fi

Замените «sh» на «bash» в зависимости от ваших потребностей.

person E Ciotti    schedule 16.07.2019

Только для проверки синтаксиса:

shellcheck [programPath]

Для запуска программы только в том случае, если синтаксис проходит успешно, поэтому отладка как синтаксиса, так и выполнения:

защищенный [programPath]

person Alberto Salvia Novella    schedule 13.02.2021