Запуск скрипта Python с помощью cron, только если он не запущен - PullRequest
16 голосов
/ 27 мая 2011

Мне нужно запускать скрипт на python (job.py) каждую минуту. Этот скрипт не должен запускаться, если он уже запущен. Время его выполнения может составлять от 10 секунд до нескольких часов.

Итак, я положил в свой crontab:

* * * * * root cd /home/lorenzo/cron && python -u job.py 1>> /var/log/job/log 2>> /var/log/job/err

Чтобы не запускать скрипт, когда он уже запущен, я использую flock ().

Это скрипт (job.py):

import fcntl
import time
import sys

def doIncrediblyImportantThings ():
    for i in range (100):
        sys.stdout.write ('[%s] %d.\n' % (time.strftime ('%c'), i) )
        time.sleep (1)

if __name__ == '__main__':
    f = open ('lock', 'w')
    try: fcntl.lockf (f, fcntl.LOCK_EX | fcntl.LOCK_NB)
    except:
        sys.stderr.write ('[%s] Script already running.\n' % time.strftime ('%c') )
        sys.exit (-1)
    doIncrediblyImportantThings ()

Этот подход, кажется, работает.

Есть ли что-то, чего мне не хватает? Есть ли проблемы, с которыми я могу столкнуться, используя этот подход?

Существуют ли более рекомендуемые или "правильные" способы достижения такого поведения?

Я благодарю вас за любое предложение.

Ответы [ 4 ]

10 голосов
/ 27 мая 2011

Единственное, что я хотел бы сделать, это сделать ваше исключение немного более конкретным.Вы не хотите случайно удалить импорт fcntl за один день и скрыть полученный результат NameError.Всегда старайтесь поймать наиболее конкретное исключение, которое вы хотите обработать.В этом случае я предлагаю что-то вроде:

import errno

try:
    fcntl.lock(...)
except IOError, e:
    if e.errno == errno.EAGAIN:
        sys.stderr.write(...)
        sys.exit(-1)
    raise

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

2 голосов
/ 28 января 2015

Я столкнулся с этой проблемой на прошлой неделе, и хотя я нашел несколько хороших решений, я решил сделать очень простой и чистый пакет python и загрузить его в PyPI.

Установить с помощью: 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

2 голосов
/ 27 мая 2011

У вас проблемы, когда машина перезагружается или зависает при работающем скрипте (и, следовательно, при активной блокировке).Простой способ противостоять этому - использовать метку времени @reboot cron для запуска rm /path/to/lock.

0 голосов
/ 30 мая 2011

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

Вы можете даже настроить его для запуска экземпляра сразу после этого, если выполняется определенное условие.

(Боюсь, что сайт немного простоват, но проект стабилен и работает, наконец, на нескольких известных мне сайтах. Я сделаю хороший, симпатичный сайт, как только выйду v0.0.3. !)

...