Гид по технологиям

Проверка синтаксиса Bash-скриптов: bash -n и ShellCheck

6 min read DevOps Обновлено 25 Dec 2025
Проверка синтаксиса Bash: bash -n и ShellCheck
Проверка синтаксиса Bash: bash -n и ShellCheck

Используйте bash -n для быстрой синтаксической проверки скрипта и ShellCheck для глубокого анализа, подсказок и предупреждений. Добавьте ShellCheck в редактор и CI, чтобы ловить ошибки до запуска и снизить риск неопределённого поведения.

Быстрые ссылки

  • Те надоедливые ошибки

  • Тестирование сложно

  • Использование bash для проверки синтаксиса

  • Утилита ShellCheck

  • Установка ShellCheck

  • Использование ShellCheck

  • ShellCheck — ваш друг

Иллюстрация: проверка синтаксиса Bash-скрипта

Введение

Ошибки и опечатки в Bash-скриптах могут привести к серьёзным последствиям при их выполнении. В этой статье показаны несколько способов проверки синтаксиса и качества shell-скриптов до запуска: встроенная проверка Bash с опцией -n и статический анализатор ShellCheck. Мы объясним, как и когда использовать каждый инструмент, какие ограничения у них есть, как интегрировать ShellCheck в рабочий процесс и дадим практические чек-листы и рекомендации.

Те надоедливые ошибки

Писать код трудно. Писать безошибочный код — ещё сложнее. Чем больше строк кода, тем выше вероятность ошибок. Язык программирования влияет на сложность: чем ближе язык к машине, тем больше забот ложится на автора. Bash — язык со своими подводными камнями: внешние утилиты, особенности подстановки, кавычек и арифметики — всё это даёт место для ошибок.

Скомпилированные языки дают частичную защиту: компилятор обнаруживает синтаксические ошибки и многие классы неграмотно написанного кода. Скриптовые языки, и особенно shell, часто не дают таких гарантий: многие ошибки проявляются только во время выполнения и зависят от окружения и входных данных.

Некоторые ошибки синтаксические — их легко отловить. Другие — логические: программа делает ровно то, что вы ей сделали написать, но не то, чего вы ожидали. Такие ошибки труднее обнаруживать автоматами и требуют тестирования и рецензирования.

Тестирование трудно

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

Для многих языков есть юнит-тесты и CI, а для shell-скриптов можно и нужно применять статический анализ и линтеры, которые помогут ловить паттерны ошибок раньше, чем они попадут в продакшен.

Использование Bash для проверки синтаксиса

Bash имеет встроенную опцию -n (noexec). Она заставляет интерпретатор прочитать скрипт и проверить синтаксис, но не выполнять его. Это безопасный способ обнаружить синтаксические ошибки, не запуская потенциально опасные команды.

Ниже — пример скрипта, который мы будем проверять. Он несложный: несколько условных операторов if. Скрипт запрашивает номер месяца (1..12) и определяет сезон. Скрипт уязвим, если пользователь не вводит данные или вводит нечисловой символ.

#! /bin/bash

read -p “Enter a month (1 to 12): “ month

if [ -z “$month” ]

then

echo “You must enter a number representing a month.”

exit 1

fi

if (( “$month” < 1 || “$month” > 12)); then

echo “The month must be a number between 1 and 12.”

exit 0

fi

if (( “$month” >= 3 && “$month” < 6)); then

echo “That’s a Spring month.”

exit 0

fi

if (( “$month” >= 6 && “$month” < 9)); then

echo “That’s a Summer month.”

exit 0

fi

if (( “$month” >= 9 && “$month” < 12)); then

echo “That’s an Autumn month.”

exit 0

fi

echo “That’s a Winter month.”

exit 0


Разберём ключевые шаги и объясним, что делает каждый фрагмент, но сначала — как запустить проверку синтаксиса.

### Как работает bash -n

Команда

bash -n ./seasons.sh


заставляет Bash прочитать скрипт и проверить грамматику и структуры управления. Если синтаксических ошибок нет, Bash тихо завершится без сообщений — «no news is good news». Если есть синтаксические ошибки, Bash выведет сообщение и номер строки.

Важно понимать пределы этой проверки:

- Она проверяет синтаксис встроенных конструкций Bash (if, for, while, функции, арифметика и т.п.).
- Bash не выполняет внешние утилиты и не проверяет, корректно ли вы используете команды вида [ или test как внешнюю программу. Поэтому ошибки, связанные с неправильным использованием внешних утилит или опечатками в их вызовах, могут не быть замечены.
- Логические ошибки и неправильные предположения о вводе не будут найдены.

## Когда bash -n не поможет (контрпримеры)

Рассмотрим несколько распространённых случаев, когда -n молчит, а при запуске скрипт ломается:

1) Ошибка в вызове внешней программы: `[` — это часто отдельная программа `/usr/bin/[`. Если вы случайно удалите открывающую квадратную скобку или используете неверный синтаксис, bash -n может не заметить эту проблему, так как она обнаруживается уже при запуске внешней команды.

2) Ошибки, зависящие от ввода: некоторые ветви кода исполняются только при конкретных вводных данных. При проверке -n Bash не выполняет код, поэтому ошибки, которые проявляются на конкретном пути выполнения, будут пропущены.

3) Неправильные права доступа, пути, переменные окружения: bash -n не учитывает окружение исполнения и права файлов; эти факторы влияют только при реальном запуске.

Пример саботажа: убрали `then` в одной из веток — bash -n может указать на синтаксическую ошибку, но если ошибка находится в ветке, которая никогда не проверяется при первом запуске без ввода, то вы можете долго не заметить проблему при реальном использовании.

## Утилита ShellCheck

ShellCheck — это статический анализатор (линтер) для shell-скриптов. Он обнаруживает ошибки, потенциальные уязвимости, шаблонные ошибки использования кавычек, подстановок, арифметики и многое другое. В отличие от bash -n, ShellCheck анализирует код более глубоко, понимает контексты использования команд и даёт рекомендуемые правки и ссылки на документацию.

Примеры того, что ShellCheck находит:

- Проблемы с кавычками и возможные разбиения слов (SC2086 и подобные).
- Небезопасное использование команд и подстановок.
- Использование устаревших или небезопасных конструкций.
- Потенциальные логические ошибки и опасности (например, чтение ввода без флага -r).

ShellCheck даёт советы и ссылки; не всё в его выводе — критично, но всё заслуживает внимания.

![ShellCheck выводит найденные ошибки и предупреждения](/files/77c8517f-d6af-4197-95f9-ce081ce60d3c.png)

## Пример: где bash -n молчит, а ShellCheck указывает на проблему

Если мы удалим открывающую скобку из условия:

if -z “$month” ] # opening bracket “[“ removed

then

echo “You must enter a number representing a month.”

exit 1

fi


Bash -n может не предупредить об этом, потому что выражение с `[` — это вызов внешней утилиты, и синтаксическая проверка не улавливает все виды неправильного её использования. ShellCheck же укажет на некорректное условие и даст рекомендации.

![Ошибка при запуске скрипта, который прошёл синтаксическую проверку](/files/d547c4c5-5fa9-4fc2-89bb-01e6651159a7.png)

## Установка ShellCheck

Установить ShellCheck можно через пакетный менеджер вашей системы. Примеры:

Ubuntu / Debian:

sudo apt install shellcheck


Fedora:

sudo dnf install ShellCheck


Manjaro / Arch-based:

sudo pacman -S shellcheck


Если необходима самая свежая версия или сборка для другой платформы, можно установить через snap, Homebrew (macOS/Linux) или собрать из исходников. Документация проекта в репозитории содержит инструкции для всех распространённых платформ.

## Использование ShellCheck

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

shellcheck seasons.sh


Вы получите список диагностических сообщений с кодами (например, SC2086) и кратким описанием проблемы. Часто ShellCheck также даёт пример исправления и ссылку на подробную страницу с объяснением.

### Пример вывода и интерпретация

Типичный вывод ShellCheck может выглядеть так (упрощённо):

- SC2148: Не указан интерпретатор в начале файла (shebang).
- SC2086: Возможное разбиение слова при использовании переменной без кавычек.
- SC2143: Использование внешней программы вместо встроенной проверки.
- SC2002: Использование cat в ситуациях, где можно обойтись без него.

Важно различать ошибки и предупреждения. Ошибки требуют немедленного исправления; предупреждения — это советы по надёжности и надёжной практике.

![ShellCheck показывает предупреждения и ошибки](/files/ffbee2c8-9544-4093-b336-a1173a43b62e.png)

## Практические рекомендации и чек-лист

Ниже — набор практических шагов и критериев, которые стоит включить в процесс разработки shell-скриптов.

Чек-лист перед коммитом:

- Запустите bash -n на скрипте.
- Запустите shellcheck и исправьте критические сообщения.
- Оцените и исправьте предупреждения, которые могут привести к неправильной обработке ввода (например, отсутствие -r у read).
- Добавьте unit-тесты или сценарии интеграционного тестирования для ключевых ветвей (например, обработка пустого ввода, нечислового ввода, крайних значений).
- Запустите скрипт в изолированной среде (контейнер или VM) с различными переменными окружения.
- Добавьте проверки на возвратные коды внешних команд и обработку ошибок.

Рольовые рекомендации:

- Разработчик: использовать ShellCheck локально, фиксировать предупреждения и документировать допущения о вводе и окружении.
- Reviewer: проверять, чтобы кавычки и проверки ошибок были везде, где требуется; убедиться, что скрипт безопасно обрабатывает ввод.
- Оператор/DevOps: интегрировать ShellCheck в CI, требовать зелёного статуса линтера перед деплоем.

## Мини-методология для исправления ошибок

1. Запустите bash -n, исправьте синтаксические ошибки.
2. Запустите shellcheck, исправьте ошибки уровня error.
3. Рассмотрите предупреждения; при сомнениях — исправьте и документируйте причину.
4. Добавьте тесты и прогоните сценарии с разными входными данными.
5. Интегрируйте линтер в CI и pre-commit hook.

## Примеры распространённых предупреждений ShellCheck и как их исправлять

- SC2086 (word splitting): всегда кавычьте переменные, когда ожидаете одну строку: use "${var}" вместо ${var}.

- SC2164 (check cd): после cd проверяйте код возврата или используйте `cd dir || exit 1`.

- SC2006/SC2034 (невостребованные переменные/команды): убирайте мёртвый код или документируйте намерение.

- Read without -r: рекомендуется `read -r var` чтобы не интерпретировать обратные слэши как escape-последовательности.

## Интеграция ShellCheck в рабочие процессы

1) Редакторы: многие плагины для VS Code, Vim, Emacs поддерживают ShellCheck и показывают предупреждения прямо при редактировании.
2) Pre-commit: добавьте shellcheck в цепочку pre-commit, чтобы не позволять коммитить плохой код.
3) CI/CD: добавьте этап линтинга в pipeline — если ShellCheck находит ошибки уровня error, сборка должна падать.
4) Обучение команды: раз в квартал проводите внутренние ревью common mistakes и демонстрации выводов ShellCheck.

Пример простой интеграции в GitHub Actions:

name: Shell Lint

on: [push, pull_request]

jobs: shellcheck:

runs-on: ubuntu-latest
steps:
  - uses: actions/checkout@v2
  - name: Install shellcheck
    run: sudo apt-get update && sudo apt-get install -y shellcheck
  - name: Run ShellCheck
    run: |
      find . -type f -name "*.sh" -not -path "./.git/*" -print0 | xargs -0 shellcheck

## Шаблоны и сниппеты

Примеры полезных сниппетов и заглушек, которые можно использовать в шаблонах скриптов:

Пример безопасного чтения ввода и проверки числового значения:

read -r -p “Enter a month (1 to 12): “ month if [ -z “$month” ]; then echo “You must enter a number representing a month.” >&2 exit 1 fi if ! [[ “$month” =~ ^[0-9]+$ ]]; then echo “The month must be a number between 1 and 12.” >&2 exit 1 fi


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

## Критерии приёмки

Перед слиянием ветки с изменением shell-скриптов, убедитесь, что выполняются следующие критерии:

- Скрипт проходит bash -n без ошибок.
- ShellCheck не возвращает ошибок уровня error.
- Критические предупреждения исправлены или задокументированы.
- Добавлены тесты/инструкции по ручному тестированию ключевых путей.
- Скрипт выполняется в изолированной среде и корректно обрабатывает невалидный ввод.

## Decision flowchart (Mermaid)

flowchart TD A[Есть скрипт?] –> B{Нужно только синтаксически проверить} B – Да –> C[bash -n] C –> D{Ошибки?} D – Да –> E[Исправить синтаксис] D – Нет –> F[Запустить ShellCheck] B – Нет –> F F –> G{ShellCheck вернул ошибки} G – Да –> E G – Нет –> H[Добавить в pre-commit и CI] E –> C


## Политика безопасности и приватность

- ShellCheck анализирует локальные файлы; при использовании онлайн-сервисов или веб-интерфейса не загружайте секреты.
- В CI-пайплайне избегайте вывода секретных значений в логах; используйте masked secrets.

## Совместимость и миграция

- ShellCheck покрывает POSIX shell и различные расширения Bash. Обратите внимание на различия между dash и bash: скрипт, написанный для Bash, может не работать в sh/dash.
- Для переносимости используйте POSIX-совместимые конструкции, если скрипт должен работать в /bin/sh.

## Рольовые чек-листы

Разработчик:

- Запустил bash -n и shellcheck.
- Закрыл критические сообщения.
- Добавил тестовый сценарий на крайние случаи.

Рецензент:

- Проверил кавычки и обработки ошибок.
- Убедился, что нет ненужных вызовов внешних программ.
- Проверил документацию и допустимые входные значения.

Оператор:

- Убедился, что скрипт запускается в target-окружении.
- Добавил мониторинг и джоб для периодической проверки скриптов.

## Факт-бокс

- bash -n: синтаксическая проверка, не выполняет команд.
- ShellCheck: статический анализатор, даёт советы и ссылки.
- Интеграция в CI и pre-commit повышает качество кода.

## Короткое объявление (100–200 слов)

ShellCheck и встроенная проверка bash -n значительно упрощают создание надёжных Bash-скриптов. Bash -n быстро находит синтаксические ошибки без запуска кода; ShellCheck идёт дальше, указывая на потенциальные уязвимости, ошибки кавычек и плохие практики. Добавьте ShellCheck в редактор, pre-commit hook и CI, чтобы находить проблемы раньше и снижать риск запуска некорректных скриптов в продакшене. Этот простой набор инструментов и практик — быстрый путь к более предсказуемым и безопасным shell-скриптам.

## Сводка

- Используйте bash -n для быстрой проверки синтаксиса.
- Используйте ShellCheck для детального анализа и советов.
- Интегрируйте ShellCheck в редактор и CI.
- Следуйте чек-листам и критериям приёмки, чтобы минимизировать риски.

### Словарь (в 1 строке)

- Linтер: инструмент статического анализа кода, который указывает на потенциальные ошибки и нарушения стиля.

![Тестирование скрипта с множеством валидных и невалидных вводов](/files/d8aa95cd-9184-4795-8973-f4632fb7ed9a.png)

![Тестирование скрипта с невалидным и валидным вводом](/files/ad9be866-4b5b-4bbb-bb91-cd02fd9c9ae6.png)
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Добавление линзовых бликов в Photoshop
Фото

Добавление линзовых бликов в Photoshop

Как обновить Discord на всех устройствах
Руководство

Как обновить Discord на всех устройствах

Оптимизация SSD: AHCI, TRIM и прошивки
Hardware

Оптимизация SSD: AHCI, TRIM и прошивки

Wide Spectrum в FaceTime на Mac — как включить
Mac

Wide Spectrum в FaceTime на Mac — как включить

Основы Git и GitHub: создать репозиторий
GIT

Основы Git и GitHub: создать репозиторий

Теги спойера в Discord — как скрывать сообщения
Руководство

Теги спойера в Discord — как скрывать сообщения