Часто люди бездумно засовывают в крон запуск долгоиграющих скриптов и потом ловят кучу багов.

К примеру, некий скрипт запускается в кроне каждый час. В какой-то момент время выполнения скрипта начинает составлять 70 и более минут. Соответственно следующий джоб через 60 минут запустит еще одну копию этого скрипта. И понеслась 3.14зда по кочкам.

Я ловил у ребят подобные перлы, когда сервер просто раком встает, а в фоне крутятся 100500 процессов, которые насилуют mysql как портовую шлюху, вдоль и поперек.

На такие случаи необходимо проверять, запущен ли скрипт в данный момент. И если запущен, то при повторном запуске — ничего не делать.

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
На такие случаи необходимо проверять, запущен ли скрипт в данный момент. И если запущен, то при повторном запуске — ничего не делать.

Как такое реализовать? В бест-практиках это реализуется через lock-файлы. Для удобства работы с lock-файлами, в Linux есть коробочный вариант утилиты, которая называется flock.

flock — утилита, которая позволяет использовать лок-файл для предотвращения запуска копии процесса (вашего скрипта, крона или чего-то еще). Например, используя cron нужно быть уверенным, что предыдущий запуск вашего скрипта уже завершен.

Пишем обработчик:

#!/bin/bash

lock="/tmp/bashdays.lock"

[[ -f "${lock}" ]] || touch "${lock}"

(
    flock -n -o -x ${fd_lock} || { echo 'Nice try' >&2; exit 0; }

    sleep 100

) {fd_lock}<"${lock}"

Запускаем скрипт. Ничего полезного он не сделает, просто будет висеть 100 секунд. После того как ты запустил этот скрипт, в соседнем терминале попробуй запустить его же параллельно. В ответ ты получишь ожидаемое — Nice try.

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

Сначала создается lock-файл, если его нет, а далее начинается магия с дескрипторами и логикой.

Вместо sleep можно вставить запуск функции типа main() где и будет основная логика скрипта. Либо вообще через source (или точку) заинклудить свой скрипт. То есть можно сделать универсальную штуку, чтобы в каждый скрипт не пихать flock.

Делаешь один обработчик и передаешь ему параметром путь до скрипта + путь до lock-файла. А обработчик через source подгружает уже полезную нагрузку.

Моё решение возможно не самое изящное, но рабочее. Изучай. Слышал, что такое можно провернуть каким-то образом через сокеты, но особо не вникал. Если в комментах поделишься, будет очень полезно. Спасибо!