| name | bash-pro |
| description | Защищённое (defensive) написание Bash-скриптов для production: strict mode, безопасный парсинг аргументов, валидация ввода, корректная очистка ресурсов. Триггер — задачи на CI/CD, ops-скрипты, hardening. |
| risk | critical |
| source | community |
| date_added | 2026-02-27 |
Skill: bash-pro
Углублённый профиль для написания и ревью Bash-скриптов с упором на безопасность, переносимость и тестируемость.
Когда использовать
- Пишешь или ревьюишь Bash-скрипт для автоматизации, CI/CD или ops.
- Усиливаешь существующий shell-скрипт по безопасности и переносимости.
Когда не использовать
- Нужен только POSIX-shell без bash-расширений.
- Логика сложная — лучше Python/Go.
- Нужна нативная Windows-автоматизация — это PowerShell.
Алгоритм
- Зафиксируй вход, выход и режимы отказа скрипта.
- Включи strict mode и безопасный парсинг аргументов.
- Реализуй основную логику с защитными паттернами.
- Покрой
bats (тесты) и shellcheck (статический анализ).
Strict mode и базовая защита
#!/usr/bin/env bash
set -Eeuo pipefail
shopt -s inherit_errexit
IFS=$'\n\t'
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
trap 'echo "Error at line $LINENO: exit $?" >&2' ERR
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
Ключевые правила
- Всегда оборачивай переменные в кавычки (
"$var") — иначе word-splitting и globbing создадут трудно ловимые баги.
- Не используй
eval на пользовательском вводе — используй массивы для динамического построения команд.
- Заменяй
for f in $(ls) на find ... -print0 | while IFS= read -r -d '' f; do ...; done (NUL-safe).
- Завершай парсинг опций через
--: rm -rf -- "$user_input".
- Валидируй обязательные переменные:
: "${REQUIRED_VAR:?not set}".
- Объявляй константы как
readonly, локальные переменные функций — через local.
mktemp + trap для всех временных файлов и каталогов.
printf вместо echo для предсказуемого форматирования.
$( ) вместо backticks — читаемее и nestable.
- Bash 4.4+ для
inherit_errexit — иначе set -e не пробрасывается через подоболочки.
- Проверка версии Bash:
(( BASH_VERSINFO[0] >= 4 && BASH_VERSINFO[1] >= 4 )).
Безопасный парсинг аргументов
usage() {
cat <<EOF
Usage: $(basename "$0") [options] <args>
-v, --verbose Verbose output
-h, --help Show this help
EOF
}
while [[ $# -gt 0 ]]; do
case $1 in
-v|--verbose) verbose=1; shift ;;
-h|--help) usage; exit 0 ;;
--) shift; break ;;
-*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
*) break ;;
esac
done
Тестирование и анализ
| Инструмент | Назначение |
|---|
| ShellCheck | Статический анализатор Bash. Включить enable=all, external-sources=true. |
| shfmt | Форматирование (-i 2 -ci -bn -sr -kp). |
| bats-core | Тестовый фреймворк (TAP-совместимый). |
| shellspec | BDD-стиль с богатыми ассертами и моками. |
| checkbashisms | Найти bash-измы для портирования на POSIX. |
Минимальный CI-пайплайн: shellcheck *.sh && shfmt -d *.sh && bats test/.
Чего избегать (типовые ловушки)
for f in $(ls ...) — словесплит и glob-баги (используй find -print0 + read -r -d '').
- Незакавыченные переменные → подстановки разлетаются.
- Вера в
set -e без trap ERR и inherit_errexit в сложных пайпах.
echo для данных (используй printf).
- Отсутствие
EXIT-trap на временные ресурсы.
- Заполнение массива через
arr=( $(cmd) ) — используй mapfile/readarray.
Полезные продвинутые приёмы
- Параметрические разворачивания:
${file%.sh} — убрать расширение, ${path##*/} — basename, ${str//old/new} — замена.
- Ассоциативные массивы:
declare -A config=([host]=localhost [port]=8080).
- Nameref:
declare -n ref=varname — ссылка на другую переменную (Bash 4.3+).
- Параллельность:
xargs -P "$(nproc)" -n 1 cmd или wait -n для любого фонового задания.
- Сигналы:
trap cleanup SIGHUP SIGINT SIGTERM для корректного шатдауна.
- Brace expansion:
touch file{1..10}.txt.
Чек-лист качества
Источники
Ограничения
- Применяй скилл только когда задача явно подпадает под defensive Bash scripting.
- Не считай вывод заменой реальной валидации, тестов на целевой системе или экспертного ревью.
- Останови работу и задай уточняющий вопрос, если не хватает входных данных, прав, границ безопасности или критериев успеха.
Внимание для текущего проекта: в Telegram-боте на момент написания скилла нет shell-tool — агент не может выполнять bash-команды напрямую. Скилл полезен только если задача про написание/ревью bash-скриптов как текста (например, пользователь прислал скрипт и просит проверить).