Как я могу заблокировать задание cron, если предыдущий запуск не был завершен. Это задание cron, которое выполняется каждые 5 минут, но иногда для его выполнения требуется более 5 минут.
редактировать Скрипт, который вызывается, иногда дает сбой! Таким образом, он не может удалить файл блокировки.
Использовать flock(1)
:
NAME
flock - manage locks from shell scripts
SYNOPSIS
flock [options] <file> -c <command>
flock [options] <directory> -c <command>
flock [options] <file descriptor number>
[...]
Вы можете заблокировать его или сразу выйти. Наличие (или отсутствие) файла блокировки не имеет значения. При необходимости он создает файл и использует flock()
системный вызов для блокировки файла. Эта блокировка автоматически снимается при смерти процесса.
Например, в cron:
*/5 * * * * /usr/bin/flock /tmp/my.lock /usr/local/bin/myjob
Если ваша работа не всегда заканчивается за 5 минут, вы можете подумать об использовании --timeout
чтобы ваши вакансии не стояли в очереди:
flock --timeout=300
Или используйте --nonblock
немедленно выйти - это было бы похоже на --timeout=0
Если ваш сценарий является сценарием оболочки, вы можете использовать некоторые хитрые уловки перенаправления, чтобы использовать flock в самом сценарии:
(
flock -n 9 || exit 1
# ... commands executed under lock ...
) 9>/var/lock/mylockfile
Или в руководстве также предлагается сделать ваш скрипт рекурсивным, поместив его вверху (он использует сам скрипт как свой файл блокировки):
[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :
Увидеть flock(1)
справочная страница для получения дополнительной информации
Pid-файлы - это путь, однако, как и сценарии инициализации, не сдаются, когда они видят файл pid, вы должны проверить, чтобы убедиться, что pid в файле все еще существует.
Что-то вроде этого поможет:
PIDFILE=/var/run/myscript.pid
if [ -e "$PIDFILE" ] ; then
# our pidfile exists, let's make sure the process is still running though
PID=`/bin/cat "$PIDFILE"`
if /bin/kill -0 "$PID" > /dev/null 2>&1 ; then
# indeed it is, i'm outta here!
/bin/echo 'The script is still running, forget it!'
exit 0
fi
fi
# create or update the pidfile
/bin/echo "$$" > $PIDFILE
... do stuff ...
/bin/rm -f "$PIDFILE"
Проверка файла pid или блокировки может завершиться ошибкой, если задание cron не может очистить файл после выхода. Я считаю, что лучший вариант - проверить сам процесс, например:
ps -ef | grep script_name | grep -v grep | wc -l
Это даст вам количество процессов с именем script_name. Вы можете проверить это количество в начале выполнения вашего скрипта.
Вы не можете, cronjobs не имеют этой функции. Поместите что-нибудь в свой сценарий, чтобы проверить это, или попросите его создать файл по завершении и использовать что-то вроде inotifywait для блокировки.
Найдите файл, например, в /var/run
. Если файл найден, выйдите. В противном случае создайте файл, запустите процедуру, а затем удалите файл.
Есть много способов. Популярным является использование файла блокировки.
1) Когда скрипт запускается, он проверяет, есть ли файл блокировки (например, /var/lock/powtac.loc
) уже присутствует.
2) Если он существует, сценарий прерывается, если предыдущий сценарий все еще выполняется *).
3) Если он не существует, скрипт создает файл и продолжает делать все, что ему нужно.
4) При выходе скрипт удаляет файл блокировки.
*) На этом этапе также можно проверить список процессов, найти совпадения для вашего задания cron и, если они найдены, узнать, когда они были запущены. Если недавно, то предположите, что они все еще работают, если давноооооооооо давно, тогда предположите, что они застряли.
У меня не было бы двух заданий cron, у меня было бы одно.
* * * * * /some/command && /some/other/command
Он будет запущен только в том случае, если первая команда завершится успешно, и только после того, как она будет выполнена.
(примечание: если вам нужно, чтобы это было через несколько минут после использования sleep
)