Одна из классических проблем в автоматизации: скрипт еще не успел завершиться, а cron, systemd timer или админ руками запускает его снова. В итоге получаем неприятные эффекты: два бэкапа пишут в один каталог, две задачи одновременно чистят одни и те же файлы, несколько копий скрипта дергают API, повторный запуск ломает промежуточное состояние, база получает дубли или конфликтующие операции и т.д. Чтобы этого избежать, удобно использовать flock.
flock - это утилита для работы с файловыми блокировками. Идея простая: перед запуском скрипт пытается взять lock-файл. Если блокировка уже занята, значит другая копия скрипта еще работает.
▪️ Самый простой вариант:
flock -n /tmp/myjob.lock /opt/scripts/myjob.sh
/tmp/myjob.lock - файл блокировки-n - не ждать освобождения lock, а сразу завершиться/opt/scripts/myjob.sh - команда, которую нужно выполнитьЕсли первый запуск еще работает, второй просто не стартует.
▪️ Для cron это выглядит так:
*/5 * * * * flock -n /tmp/backup.lock /opt/scripts/backup.sh
`
Теперь даже если бэкап длится дольше 5 минут, новая копия не запустится поверх старой.
▪️ Можно добавить логирование:
flock -n /tmp/backup.lock /opt/scripts/backup.sh || echo "backup already running"
▪️ Но часто удобнее встроить flock прямо в сам скрипт:
#!/usr/bin/env bash
set -euo pipefail
LOCK_FILE="/tmp/myjob.lock"
exec 200>"$LOCK_FILE"
flock -n 200 || {
echo "script already running"
exit 1
}
echo "start job"
# основная логика скрипта
sleep 30
echo "done"
exec 200>"$LOCK_FILE" открывает lock-файл на файловом дескрипторе 200flock -n 200 пытается взять блокировкуесли блокировка занята - скрипт завершается
пока скрипт работает, дескриптор открыт и lock удерживается
После завершения процесса блокировка освобождается автоматически.
▪️ Где хранить lock-файл? Для временных задач часто используют:
/tmp/myjob.lock
Для системных сервисов лучше:
/run/myjob.lock
/run обычно живет в tmpfs и очищается после перезагрузки. Это удобно для runtime-блокировок.▪️ Есть и режим ожидания:
flock /tmp/myjob.lock /opt/scripts/myjob.sh
В этом случае второй запуск будет ждать, пока первый освободит lock.
Можно задать таймаут ожидания:
flock -w 60 /tmp/myjob.lock /opt/scripts/myjob.sh
Так команда подождет до 60 секунд и завершится, если блокировка не освободится.
#bash #flock
🧑💻 NetworkAdmin