严格执行cron,仅确保单个实例


9

有没有办法每分钟(或2,或5等)运行脚本,但前提是脚本尚未运行?

我们有一组脚本,需要每分钟运行一次。有时他们可能会在一秒钟内开始和结束,而其他时候可能会持续5分钟。

我们当前避免同时执行的方法是is_running在每个脚本中设置一个标志,如果仍然启用则退出。但这有点不可靠(即致命错误将导致该标志即使在脚本停止后仍保持启用状态)。

我们可以写自己的小经理,但是我想知道是否已经存在一个更时尚的解决方案。


+1我也对此感兴趣。我不知道答案,但是我对可能的解决方案感兴趣。
Saif Bechan 2010年

一分钟的cron闻到很多“使我成为守护进程”的气味
AD7six

Answers:


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文档...

如果您想特别懒惰;-)如果对ps输出进行greps使进程正在运行,则只需退出脚本即可。但是最好使用lock / pid文件。


anacron是cron的更新版本,因此比旧标准具有更多功能。关于“如何”,它可能注册了一个SIGCHLD处理程序,该处理程序在子进程死亡时触发。因此,它可以跟踪正在运行的孩子,而只需跳过这些工作即可。
哈维尔2010年

// @哈维尔:我不同意“ anacron是cron的更新版本,因此它比旧标准具有更多功能”。做什么anacroncron做什么之间有一些重叠,但是它们解决了不同的问题。使用cron,您将如何开始因机器故障而错过的工作?使用anacron,您将如何在12月25日或每5分钟开始工作?(您当然可以使用脚本解决方法,但这不是我正在谈论的内容。)
已暂停,直到另行通知。

@Kyle:该选项会使安排在同一时间运行的不同作业一次运行。它可能满足OP的需要,但会阻止其他作业或其他作业会阻止它。另外,anacron运行时间不得短于一天。
暂停,直到另行通知。

@丹尼斯·威廉姆森(Dennis Williamson):我想您是对的,我还没有检查历史记录的详细信息。但是我仍然相信您会同意anacron项目是在cron成立之后开始的,并且受到了它的启发;因此,它具有cron没有的功能并不令人惊讶。另外,原来的问题是关于cron的
哈维尔

1

这是该方法的正确解决方案。通常,将使用pid文件,并对进程进行pid测试以确保其正在运行。如果过时,则将删除锁定文件,并且该过程仍将运行。

与在cron中运行相反,通常会将任何其他智能作为守护程序写入软件本身。


1

如果您的脚本使用支持flock(2)syscall的语言进行编码,则也可以使用函数调用将flock()锁定文件。例:

如果您坚持使用不支持此功能的Bash或其他脚本语言,那么使用flock(1)提出的解决方案也可以。

PS无论如何,您仅应创建一个单独的锁定文件(如果尚不存在),则永远不要删除它。目录“ / var / lock”是此类文件的好地方。


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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.