Мелкий крон, обеспечивающий только один экземпляр

9

Есть ли способ запускать скрипт каждую минуту (или 2, или 5 и т. Д.), Но только если он еще не запущен?

У нас есть набор скриптов, которые нужно запускать каждую минуту. Иногда они могут начинаться и заканчиваться через секунду, в других случаях они могут продолжаться в течение 5 минут.

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

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

chroder
источник
+1 Меня это тоже интересует. Я не знаю ответа, однако меня интересуют возможные решения.
Саиф Бечан
Мелкий крон пахнет "сделай меня демоном"
AD7six

Ответы:

8

лучший способ - использовать flockвместо pidfile. проверьте справочную страницу: flock (1) . Преимущество состоит в том, что независимо от того, как процесс завершается / умирает, блокировка исчезает вместе с ним.

Хавьер
источник
3

Я бы предпочел согласиться с ответом файла pid Уорнера. Однако достигает ли следующая особенность Anacron этого?

-s
    Serialize execution of jobs. Anacron will not start a new job before the previous one finished. 

Я не проверял это сам, я не нахожу документацию Anacron достаточно тщательно ...

Если вы хотите быть особенно ленивым ;-) Вы можете просто выйти из скрипта, если grepe через вывод ps вернет процесс как работающий. Но файл блокировки / pid лучше.

Кайл Брандт
источник
anacron является более поздней версией cron, поэтому он имеет больше возможностей, чем старый стандарт. Что касается «как», он, вероятно, регистрирует обработчик SIGCHLD, который запускается, когда умирает дочерний процесс. таким образом, он может следить за запущенными детьми и просто пропустить эти задания.
Хавьер
@ Хавьер: я не согласен с «anacron является более поздней версией cron, поэтому он имеет больше возможностей, чем старый стандарт». Между тем, что anacronи cronесть, есть некоторое совпадение , но они решают разные проблемы. Используя cron, как бы вы начали работу, которая была пропущена, потому что машина не работала? Используя anacron, как бы вы начать работу каждый 25 декабря или через каждые 5 минут? (Можно, конечно, обойти сценарий, но я не об этом.)
Пауза до дальнейшего уведомления.
@Kyle: эта опция позволяет запускать разные задания, запланированные на одно и то же время. Это может сработать для нужд ОП, но оно заблокирует другие задания или другие задания заблокируют его. Кроме того, anacronне работает в периоды короче, чем день.
Приостановлено до дальнейшего уведомления.
@ Денис Уильямсон: я думаю, вы правы, я не проверял детали истории. Но все же я думаю, вы согласитесь, что проект anacron начался после того, как cron был в значительной степени создан и вдохновлен им; поэтому не удивительно, что у него есть функции, которых нет у cron. Кроме того, оригинальный вопрос был о cron
Javier
1

Это правильное решение для этого подхода. Как правило, файл pid будет использоваться, и pid тест будет проводиться против процесса, чтобы убедиться, что он работает. Если он устарел, файл блокировки будет удален, и процесс все равно будет запущен.

Любой дополнительный интеллект обычно записывается в самом программном обеспечении как демон, а не в cron.

сигнализатор
источник
1

Если ваши скрипты написаны на языке, который поддерживает системный вызов flock (2), то вы можете flock () заблокировать файл также с помощью вызова функции. Пример:

Если вы застряли в Bash или другом языке сценариев, который этого не поддерживает, то уже предложенное решение с flock (1) тоже подойдет.

PS В любом случае вы должны создать отдельный файл блокировки только один раз (если он еще не существует) и никогда не удалять его. Каталог "/ var / lock" является хорошим местом для таких файлов.

famzah
источник
0

Это решение, если ваш скрипт выполняется на python (или вы можете создать команду python для запуска перед следующей командой) - я столкнулся с этой проблемой на прошлой неделе, и хотя я нашел несколько хороших решений, я решил сделать очень простой и чистый пакет Python и загрузил его в PyPI. Конечно, вы можете заблокировать, __file__чтобы не думать о присвоении ему имени ресурса для блокировки.

Установить с помощью: pip install quicklock

Используя это чрезвычайно просто:

[nate@Nates-MacBook-Pro-3 ~/live] python
Python 2.7.6 (default, Sep  9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from quicklock import singleton
>>> # Let's create a lock so that only one instance of a script will run
...
>>> singleton('hello world')
>>>
>>> # Let's try to do that again, this should fail
...
>>> singleton('hello world')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/nate/live/gallery/env/lib/python2.7/site-packages/quicklock/quicklock.py", line 47, in singleton
    raise RuntimeError('Resource <{}> is currently locked by <Process {}: "{}">'.format(resource, other_process.pid, other_process.name()))
RuntimeError: Resource <hello world> is currently locked by <Process 24801: "python">
>>>
>>> # But if we quit this process, we release the lock automatically
...
>>> ^D
[nate@Nates-MacBook-Pro-3 ~/live] python
Python 2.7.6 (default, Sep  9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from quicklock import singleton
>>> singleton('hello world')
>>>
>>> # No exception was thrown, we own 'hello world'!

Взглянуть: https://pypi.python.org/pypi/quicklock

Нейт Ферреро
источник