Як синтаксис перевірити сценарій Bash, не запускаючи його?


267

Чи можна перевірити синтаксис bash script, не виконуючи його?

Використовуючи Perl, я можу працювати perl -c 'script name'. Чи є еквівалентна команда для bash-скриптів?


Відповіді:


380
bash -n scriptname

Можливо, очевидний застереження: це перевіряє синтаксис, але не перевірить, чи ваш скрипт bash намагається виконати команду, яка не знаходиться на вашому шляху, як ech helloзамість echo hello.


9
У програмі bash у розділі "SHELL BUILTIN COMMANDS / set" документація -n задокументована, і, як стверджується початок manpage, bash інтерпретує всі параметри одного символу, які є set.
ефемієнт

24
щоб додати до (для мене) не очевидного застереження, він також не введе помилку, спричинену відсутнім пробілом, if ["$var" == "string" ]а неif [ "$var" == "string" ]
Brynjar

11
@Brynjar Це тому, що це просто перевірка синтаксису. Відкрита дужка не є синтаксисом, це назва функції, яку потрібно запустити. type [каже "[вбудована оболонка". В кінцевому рахунку він делегує testпрограмі, але також очікує закриття дужки. Так це, як if test"$var"це не те, що мав на увазі автор, але синтаксично допустиме (скажімо, у $ var є значення "a", тоді ми побачимо "bash: testa: команда не знайдена"). Справа в тому, що в синтаксичному плані немає місця.
Джошуа Щока

2
@JoshuaCheek: [У цьому випадку Builtin викликається лише в тому випадку, якщо $varрозшириться до порожнього рядка . Якщо $varрозширюється на не порожню рядок, [вона об'єднується з цією рядком і інтерпретується як ім'я команди (не ім'я функції ) Bash, і, так, це синтаксично дійсно, але, як ви заявляєте, очевидно, не наміром. Якщо ви використовуєте [[замість [, хоча [[це ключове слово оболонки (а не вбудований), ви отримаєте той самий результат, оскільки ненавмисна конкатенація рядків все ж перекриває розпізнавання ключового слова.
mklement0

2
@JoshuaCheek: Bash ще синтаксис проверяюще тут: це перевірка простий команди виклику синтаксис: ["$var"є синтаксичний допустимим ім'ям команди вираження; Аналогічно, лексеми ==та "$string"дійсні аргументи команди . ( Як правило, вбудований [розбираються з командою синтаксисом, тоді [[- як оболонка ключовим слова - аналізуються по- різному.) Вбудована команда оболонки [ніяк НЕ делегує на « testпрограму» (зовнішня утиліта): bash, dash, ksh, zshвсі вони мають вбудовану команду версії як [іtest, і вони не називають своїх зовнішніх комунальних аналогів.
mklement0

127

Час все змінює. Ось веб-сайт, який забезпечує перевірку синтаксису в Інтернеті для сценарію оболонки.

Я виявив, що це дуже потужне виявлення поширених помилок.

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

Про ShellCheck

ShellCheck - це інструмент для статичного аналізу та зв'язування для скриптів sh / bash. Основна увага зосереджена на обробці типових помилок синтаксису для початківців та проміжних рівнів, де оболонка просто дає критичне повідомлення про помилку або дивну поведінку, але також повідомляє про ще кілька вдосконалених питань, коли кутові випадки можуть спричинити затримки відмов.

Вихідний код Haskell доступний на GitHub!


5
Чудовий наконечник; На OSX тепер також можна встановити CLI shellcheck.net shellcheck, через Homebrew : brew install shellcheck.
mklement0

3
Також про debian & friends:apt-get install shellcheck
той інший хлопець

Для надійного Ubuntu цей пакет повинен бути встановлений з trusty-backports.
Петерино

Як було сказано вище, потрібна довірна залежність, і ви можете встановити її як нижче в ubuntu 14.04: sudo apt-get -f install, тоді: sudo sudo apt-get install shellcheck
zhihong

Це дійсно корисно, але воно використовує не парсер Баша, а власний. У більшості випадків це досить добре, і це дозволяє виявити як розбір, так і інші проблеми, але є принаймні один крайній випадок (і, мабуть, інші, які я не бачив), де він не аналізує зовсім однаково.
Даніель Н

38

Я також вмикаю опцію 'u' для кожного сценарію bash, який я пишу, щоб зробити додаткову перевірку:

set -u 

Це повідомить про використання неініціалізованих змінних, як у наступному скрипті "check_init.sh"

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

Запуск сценарію:

$ check_init.sh

Повідомлять про наступне:

./check_init.sh evidence4]: повідомлення: Параметр не встановлено.

Дуже корисно ловити помилки


4
я встановлюю ці прапори завжди в моїх скриптах bash, якщо вони передають ці, добре перейти "set -o errexit" "set -o nounset" "set -o pipefail"
μολὼν.λαβέ

+1, set -uхоча це насправді не відповідає на питання, оскільки вам потрібно запустити сценарій, щоб отримати повідомлення про помилку. Навіть не bash -n check_init.shвидно, що попередження
rubo77

23
sh  -n   script-name 

Виконати це. Якщо в скрипті є якісь синтаксичні помилки, то він повертає те саме повідомлення про помилку. Якщо помилок немає, то воно виходить, не даючи жодного повідомлення. Ви можете перевірити негайно, використовуючи echo $?, що повернеться0 підтвердження успішного без будь-якої помилки.

Це працювало для мене добре. Я працював на ОС Linux, Bash Shell.


1
Хоча це зовсім не стосується перевірки синтаксису bash - використання набору -x та set + x для налагодження повного сценарію або розділів сценарію є досить корисним
GuruM

Дякую за це, я не знав, що не знав про -n, але те, що я хотів, це @GuruM> sh -x test.sh, що відображає генерований вихід сценарію
zzapper

1
Так. Я забув зазначити, що ви можете виконати наступне. У командному рядку: 1) bash -x test.sh # цей запускає весь сценарій у режимі налагодження 2) set + x; bash test.sh; встановити -x #set режим налагодження увімкнено / вимкнено до / після запуску сценарію У сценарії: a) #! / bin / bash -x #add 'режим налагодження' у верхній частині сценарію b) встановити + x; код; встановіть -x #add 'режим налагодження' для будь-якого розділу сценарію
GuruM

sh -nнапевно не перевірять, чи справжній сценарій Bash-скрипт. Це може дати помилкові негативи. sh- це варіант оболонки Борна, який зазвичай не є Bash. Наприклад, Ubuntu Linux realpath -e $(command -v sh)дає / bin / dash
jarno

4

Я фактично перевіряю всі скрипти bash у поточному реєстрі на наявність синтаксичних помилок БЕЗ запускання їх за допомогою findінструменту:

Приклад:

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

Якщо ви хочете використовувати його для одного файлу, просто відредагуйте підстановку з назвою файлу.


3

команда null [двокрапка] також корисна при налагодженні, щоб побачити значення змінної

set -x
for i in {1..10}; do
    let i=i+1
    : i=$i
done
set - 

він використовує розширення параметрів
mug896

це працює, тому що set -xпоказує кожен рядок до його виконання
rubo77

1

Існує плагін BashSupport для IntelliJ IDEA, який перевіряє синтаксис.


Але це не спрацює, якщо ваші файли не закінчуються .shабо іншим розширенням, пов’язаним зі сценаріями Bash, це так, якщо ви генеруєте сценарії за допомогою якогось інструменту для створення шаблонів, такого як ERB (тоді вони закінчуються .erb). Будь ласка, голосуйте за youtrack.jetbrains.com/issue/IDEA-79574, якщо ви хочете, щоб це було виправлено!
Грег Дубіцький

1

Якщо вам потрібна змінна дійсність усіх файлів у каталозі (git попередньо здійснити гак, побудувати скрипт lint), ви можете впізнати більш жорсткий вихід команд "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" залежно від ваших потреб

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