我需要每分钟运行一个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 ()
这种方法似乎有效。
我有什么遗漏的吗?我可以使用这种方法遇到任何麻烦吗?
是否有更多建议或“正确”的方法来实现此行为?
我感谢你的任何建议。
答案 0 :(得分:10)
我要做的唯一建议是使您的异常处理更加具体。您不希望有一天意外删除fcntl
导入并隐藏结果NameError
。始终尝试捕获您想要处理的最具体的异常。在这种情况下,我建议像:
import errno
try:
fcntl.lock(...)
except IOError, e:
if e.errno == errno.EAGAIN:
sys.stderr.write(...)
sys.exit(-1)
raise
这样,任何其他导致无法获取锁定的原因都会显示(可能是因为您使用的是cron),并且您可以决定是否有管理员可以查看的内容,另一个程序要处理的情况,或其他。
答案 1 :(得分:2)
当机器重新启动或在脚本运行时冻结(因此是主动锁定)时,您遇到了麻烦。解决此问题的简单方法是使用@reboot
cron时间戳来运行rm /path/to/lock
。
答案 2 :(得分:2)
上周我遇到了这个问题,虽然我找到了一些很好的解决方案,但我决定制作一个非常简单干净的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'!
答案 3 :(得分:0)
您可以使用The Fat Controller守护程序,该守护程序将在上一个实例完成后x秒重新启动脚本,因此您永远不会有相同脚本的重叠实例。
如果满足某个条件,您甚至可以将其调整为立即启动实例。
(我担心这个网站有点基础,但是这个项目很稳定,并且在我知道的最后几个网站上运行。一旦我把v0.0.3推出门外,我会建立一个漂亮,漂亮的网站!)