Собственно, сам список сниппетов:
Пока только 2 🙃
Сниппет №1 - шебанг и базовые переменные скрипта
#!/usr/bin/env bash
# Шебанг: запускает bash, найденный через env - более переносимо, чем /bin/bash
# Параметры безопасности (повышает надёжность и предсказуемость скрипта)
set -Eeuo pipefail
# -e - выход при ошибке
# -E - trap ERR работает в функциях/subshell
# -u - ошибка при обращении к неустановленной переменной
# -o pipefail - конвейер завершается при ошибке любой команды
# Явное определение PATH
# Исключает зависимость от окружения и защищает от подмены команд
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"
# Базовые переменные
SCRIPT_PID=$$ # PID скрипта, полезно для логов и уникальных файлов
# Абсолютный путь к каталогу скрипта (без симлинков)
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P)
SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")" # Имя файла скрипта
SCRIPT_LOG="${SCRIPT_DIR}/${SCRIPT_NAME%.*}.log" # Файл лога
SCRIPT_LOG_PREFIX='[%Y-%m-%d %H:%M:%S.%3N]' # Формат метки времени
SCRIPT_LOCK="${SCRIPT_DIR}/${SCRIPT_NAME%.*}.lock" # Файл блокировки
# Используется для логирования и предотвращения одновременного запускаСкрипт включает строгий режим безопасности (set -Eeuo pipefail), задаёт безопасный PATH, определяет базовые переменные — свой PID, путь и имя, а также файлы для лога и блокировки, чтобы можно было писать логи и предотвращать одновременный запуск.
Сниппет №2 - блокировка для предотвращения повторного запуска скрипта
SCRIPT_PID=$$ # PID скрипта
# Абсолютный путь к каталогу скрипта
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P)
SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")" # Имя файла скрипта
SCRIPT_LOCK="${SCRIPT_DIR}/${SCRIPT_NAME%.*}.lock" # Файл блокировки
# Функция блокировки
setup_lock() {
# Открываем файл блокировки и сохраняем дескриптор
exec {fd_lock}>> "${SCRIPT_LOCK}"
# Пытаемся захватить блокировку (без ожидания)
if ! flock -n "$fd_lock"; then
echo "Script instance is already running, exiting..."
exit 1 # Выходим, если файл уже заблокирован
fi
# Записываем PID текущего процесса в lock-файл
echo "$SCRIPT_PID" > "$SCRIPT_LOCK"
}
# Инициализация блокировки
setup_lockЭтот код предотвращает одновременный запуск нескольких экземпляров одного и того же скрипта.
Подробнее
При запуске скрипта:
- Создаётся lock-файл рядом со скриптом (
.lock), ассоциированный с файловым дескрипторомfd_lock. flockпытается установить эксклюзивную блокировку.- если другой экземпляр уже запущен, блокировка занята - скрипт выводит сообщение и завершает работу
- если блокировка свободна, текущий процесс получает эксклюзивный доступ
- В lock-файл записывается PID, что упрощает диагностику (можно увидеть, какой процесс удерживает блокировку).
Такой механизм используется в системных и cron-скриптах, чтобы не запустить параллельно несколько копий одной задачи (например, резервного копирования или синхронизации).flock гарантирует атомарность - два процесса не смогут захватить один и тот же lock-файл одновременно.
Сниппет №3 - действия очистки при завершении скрипта
SCRIPT_PID=$$ # PID скрипта
# Абсолютный путь к каталогу скрипта
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd -P)
SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")" # Имя файла скрипта
SCRIPT_LOCK="${SCRIPT_DIR}/${SCRIPT_NAME%.*}.lock" # Файл блокировки
# Открываем файл блокировки и сохраняем дескриптор
exec {fd_lock}>> "${SCRIPT_LOCK}"
# Пытаемся захватить блокировку (без ожидания)
flock -n "$fd_lock"
# Записываем PID текущего процесса в lock-файл
echo "$SCRIPT_PID" > "$SCRIPT_LOCK"
# Функция очистки, вызываемая при завершении работы скрипта (сработке trap)
cleanup() {
# Сбрасываем все установленные trap'ы, чтобы избежать рекурсивных вызовов
trap - SIGINT SIGTERM SIGHUP SIGQUIT ERR EXIT
# Если файловый дескриптор был открыт - закрываем его
[[ -n "${fd_lock-}" ]] && exec {fd_lock}>&-
# Проверяем, существует ли lock-файл и содержит ли он PID текущего процесса
# Это предотвращает случайное удаление чужого lock-файла
if [[ -f "$SCRIPT_LOCK" && $(< "$SCRIPT_LOCK") -eq $SCRIPT_PID ]]; then
# Удаляем lock-файл, освобождая ресурс
rm -f "$SCRIPT_LOCK"
fi
}
# Устанавливаем trap (ловушку),
# чтобы при выходе из скрипта, вызывалась функция cleanup
# Старайтесь завершать trap'ы командой exit
trap 'RC=$?; cleanup; exit $RC' SIGINT SIGHUP SIGTERM SIGQUIT ERR EXITЭтот сниппет демонстрирует использование trap для вызова функции cleanup, которая обеспечивает корректное завершение скрипта и очистку ресурсов (на примере удаления lock-файла).
Подробнее
В этом сниппете удаление lock-файла - лишь пример применения механизма trap, который демонстрирует, как можно:
- отлавливать сигналы (
SIGINT,SIGTERM,SIGHUP,SIGQUIT) и ошибки (ERR,EXIT); - выполнять единый блок завершения (функция
cleanup), независимо от причины выхода скрипта; - гарантировать корректную очистку и завершение любых операций (не только lock-файлов - сюда могут входить временные файлы, сетевые соединения, монтирования и т.д.).


