Проверка выполнения скрипта CRON [duplicate]

Я ищу простое и универсальное решение, позволяющее выполнять любой скрипт или приложение в crontab и не запускать его дважды.

Решение должно быть независимым от выполненной команды.

Я предполагаю, что он должен выглядеть как lock && (command ; unlock), где lock вернет false, если была еще одна блокировка.

Вторая часть была бы такой, как если бы она приобрела блокировку, запустила команду и разблокировала после команды выполняется, даже если он возвращает ошибку.

25
задан 25 May 2012 в 14:03

14 ответов

Взгляните на пакет run-one. Из manpage для команды run-one:

run-one - это сценарий оболочки, который запускает не более одного уникального экземпляра некоторой команды с уникальным набором аргументов. Это часто полезно для cronjob, когда вы хотите, чтобы одновременно выполнялось не более одной копии.

Как и time или sudo, вы просто добавляете его в команду. Итак, cronjob может выглядеть так:

*/60 * * * * run-one rsync -azP $HOME example.com:/srv/backup

Для получения дополнительной информации и фона посмотрите run-one Dustin Kirkland.

29
ответ дан 17 July 2018 в 18:38

Взгляните на пакет run-one. Из manpage для команды run-one:

run-one - это сценарий оболочки, который запускает не более одного уникального экземпляра некоторой команды с уникальным набором аргументов. Это часто полезно для cronjob, когда вы хотите, чтобы одновременно выполнялось не более одной копии.

Как и time или sudo, вы просто добавляете его в команду. Итак, cronjob может выглядеть так:

*/60 * * * * run-one rsync -azP $HOME example.com:/srv/backup

Для получения дополнительной информации и фона посмотрите run-one Dustin Kirkland.

29
ответ дан 23 July 2018 в 19:27

Это решение для сценария bash, который должен проверять себя

v=$(pgrep -xf "/bin/bash $0 $@") [ "${v/$BASHPID/}" != "" ] && exit 0
0
ответ дан 17 July 2018 в 18:38

Простое решение от bash-hackers.org, которое работало для меня, использовало mkdir. Это простой способ убедиться, что работает только один экземпляр вашей программы. Создайте каталог с mkdir .lock, который возвращает

true, если создание было успешным и false, если файл блокировки существует, указывая на то, что в настоящее время работает один экземпляр.

Итак, эта простая функция выполнила всю логику блокировки файлов:

if mkdir .lock; then echo "Locking succeeded" eval startYourProgram.sh ; else echo "Lock file exists. Program already running? Exit. " exit 1 fi echo "Program finished, Removing lock." rm -r .lock
0
ответ дан 17 July 2018 в 18:38

См. также [4] Тима Кэя, который выполняет блокировку путем привязки порта по замкнутому адресу, уникальному для пользователя:

http://timkay.com/solo/

] В случае, если его сайт не работает:

Использование:

solo -port=PORT COMMAND where PORT some arbitrary port number to be used for locking COMMAND shell command to run options -verbose be verbose -silent be silent

Используйте его так:

* * * * * solo -port=3801 ./job.pl blah blah

Сценарий:

#!/usr/bin/perl -s # # solo v1.7 # Prevents multiple cron instances from running simultaneously. # # Copyright 2007-2016 Timothy Kay # http://timkay.com/solo/ # # It is free software; you can redistribute it and/or modify it under the terms of either: # # a) the GNU General Public License as published by the Free Software Foundation; # either version 1 (http://dev.perl.org/licenses/gpl1.html), or (at your option) # any later version (http://www.fsf.org/licenses/licenses.html#GNUGPL), or # # b) the "Artistic License" (http://dev.perl.org/licenses/artistic.html), or # # c) the MIT License (http://opensource.org/licenses/MIT) # use Socket; alarm $timeout if $timeout; $port =~ /^\d+$/ or $noport or die "Usage: $0 -port=PORT COMMAND\n"; if ($port) { # To work with OpenBSD: change to # $addr = pack(CnC, 127, 0, 1); # but make sure to use different ports across different users. # (Thanks to www.gotati.com .) $addr = pack(CnC, 127, $<, 1); print "solo: bind ", join(".", unpack(C4, $addr)), ":$port\n" if $verbose; $^F = 10; # unset close-on-exec socket(SOLO, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die "socket: $!"; bind(SOLO, sockaddr_in($port, $addr)) or $silent? exit: die "solo($port): $!\n"; } sleep $sleep if $sleep; exec @ARGV;
3
ответ дан 17 July 2018 в 18:38

Не нужно устанавливать какой-то причудливый пакет:

#!/bin/bash pgrep -xf "$*" > /dev/null || "$@"

Быстрее писать сам скрипт, чем запускать «apt-get install», не так ли? Вы можете добавить «-u & nbsp; $ (id -u)» в pgrep для проверки экземпляров, выполняемых только текущим пользователем.

3
ответ дан 17 July 2018 в 18:38

Очень простой способ установки блокировки:

if mkdir /var/lock/mylock; then echo "Locking succeeded" >&2 else echo "Lock failed - exit" >&2 exit 1 fi

Скрипты, которые нужно запустить, требуют создания блокировки. Если блокировка существует, другой скрипт занят, поэтому первый скрипт не может работать. Если файл не существует, ни один скрипт не приобрел блокировку. Таким образом, текущий скрипт получает блокировку.

Для получения дополнительной информации о блокировке bash, проверьте эту страницу

.
4
ответ дан 17 July 2018 в 18:38

Вам нужен замок. run-one выполняет задание, но вы также можете просмотреть flock из пакета util-linux.

Это стандартный пакет, предоставляемый разработчиками ядра, позволяет настраивать больше, чем run-one и все еще очень просто.

1
ответ дан 17 July 2018 в 18:38

Это решение для сценария bash, который должен проверять себя

v=$(pgrep -xf "/bin/bash $0 $@") [ "${v/$BASHPID/}" != "" ] && exit 0
0
ответ дан 23 July 2018 в 19:27

Простое решение от bash-hackers.org, которое работало для меня, использовало mkdir. Это простой способ убедиться, что работает только один экземпляр вашей программы. Создайте каталог с mkdir .lock, который возвращает

true, если создание было успешным и false, если файл блокировки существует, указывая на то, что в настоящее время работает один экземпляр.

Итак, эта простая функция выполнила всю логику блокировки файлов:

if mkdir .lock; then echo "Locking succeeded" eval startYourProgram.sh ; else echo "Lock file exists. Program already running? Exit. " exit 1 fi echo "Program finished, Removing lock." rm -r .lock
0
ответ дан 23 July 2018 в 19:27

См. также [4] Тима Кэя, который выполняет блокировку путем привязки порта по замкнутому адресу, уникальному для пользователя:

http://timkay.com/solo/

] В случае, если его сайт не работает:

Использование:

solo -port=PORT COMMAND where PORT some arbitrary port number to be used for locking COMMAND shell command to run options -verbose be verbose -silent be silent

Используйте его так:

* * * * * solo -port=3801 ./job.pl blah blah

Сценарий:

#!/usr/bin/perl -s # # solo v1.7 # Prevents multiple cron instances from running simultaneously. # # Copyright 2007-2016 Timothy Kay # http://timkay.com/solo/ # # It is free software; you can redistribute it and/or modify it under the terms of either: # # a) the GNU General Public License as published by the Free Software Foundation; # either version 1 (http://dev.perl.org/licenses/gpl1.html), or (at your option) # any later version (http://www.fsf.org/licenses/licenses.html#GNUGPL), or # # b) the "Artistic License" (http://dev.perl.org/licenses/artistic.html), or # # c) the MIT License (http://opensource.org/licenses/MIT) # use Socket; alarm $timeout if $timeout; $port =~ /^\d+$/ or $noport or die "Usage: $0 -port=PORT COMMAND\n"; if ($port) { # To work with OpenBSD: change to # $addr = pack(CnC, 127, 0, 1); # but make sure to use different ports across different users. # (Thanks to www.gotati.com .) $addr = pack(CnC, 127, $<, 1); print "solo: bind ", join(".", unpack(C4, $addr)), ":$port\n" if $verbose; $^F = 10; # unset close-on-exec socket(SOLO, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die "socket: $!"; bind(SOLO, sockaddr_in($port, $addr)) or $silent? exit: die "solo($port): $!\n"; } sleep $sleep if $sleep; exec @ARGV;
3
ответ дан 23 July 2018 в 19:27

Не нужно устанавливать какой-то причудливый пакет:

#!/bin/bash pgrep -xf "$*" > /dev/null || "$@"

Быстрее писать сам скрипт, чем запускать «apt-get install», не так ли? Вы можете добавить «-u & nbsp; $ (id -u)» в pgrep для проверки экземпляров, выполняемых только текущим пользователем.

3
ответ дан 23 July 2018 в 19:27
  • 1
    это не гарантирует один экземпляр. два сценария могут перейти на другую сторону оператора || одновременно, прежде чем либо еще есть шанс запустить скрипт. – Sedat Kapanoglu 9 August 2016 в 23:45
  • 2
    @SedatKapanoglu Предоставлено, что этот сценарий не является оправданием гонки, но исходный вопрос касался длительных рабочих заданий cron (которые запускаются не чаще одного раза в минуту). Если вашей системе требуется больше минуты для создания процесса, у вас есть другие проблемы. Однако, если необходимо по каким-либо другим причинам, вы можете использовать стадо (1) для защиты выше сценария от условий гонки. – Michael Kowhan 11 August 2016 в 01:59
  • 3
    Я использовал это, но для сценария bash, который должен проверять себя. Код следующий: v = $ (pgrep -xf "/ bin / bash $ 0 $ @") [& quot; $ {v / $ BASHPID /} & quot; ! = "& quot; ] & amp; & amp; выход 2 – ahofmann 19 January 2017 в 17:14

Очень простой способ установки блокировки:

if mkdir /var/lock/mylock; then echo "Locking succeeded" >&2 else echo "Lock failed - exit" >&2 exit 1 fi

Скрипты, которые нужно запустить, требуют создания блокировки. Если блокировка существует, другой скрипт занят, поэтому первый скрипт не может работать. Если файл не существует, ни один скрипт не приобрел блокировку. Таким образом, текущий скрипт получает блокировку.

Для получения дополнительной информации о блокировке bash, проверьте эту страницу

.
4
ответ дан 23 July 2018 в 19:27
  • 1
    Вам также понадобится ловушка EXIT, которая удалит блокировку при выходе. [F1] – geirha 25 May 2012 в 15:23
  • 2
    В идеале вы хотели бы использовать консультативную стаю из процесса, который выполняет команду, которую вы хотите в качестве подзадачи. Таким образом, если все они умирают, стая автоматически освобождается, что не позволяет использовать наличие файла блокировки. Использование сетевого порта будет работать аналогичным образом, хотя это путь меньшее пространство имен, что является проблемой. – Alex North-Keys 19 March 2015 в 20:45

Вам нужен замок. run-one выполняет задание, но вы также можете просмотреть flock из пакета util-linux.

Это стандартный пакет, предоставляемый разработчиками ядра, позволяет настраивать больше, чем run-one и все еще очень просто.

1
ответ дан 23 July 2018 в 19:27

Другие вопросы по тегам:

Похожие вопросы: