我已经将我的网络服务器 cron 作业配置为每 15 分钟触发一些 PHP 脚本,但有时当同一脚本的另一个进程启动时,该脚本需要超过 15 分钟才能完成执行。这给我们的逻辑带来了问题。我只想运行同一进程的一个实例,如果它完成,则只让另一个进程执行(不想将进程放入队列中,只需在那一刻终止并在下一个时间间隔执行)。
示例:我有三个 PHP 文件,网络服务器 cron 作业每 15 分钟就会调用一次。假设a.php、b.php、c.php。该脚本可能需要 15 分钟以上才能完成执行。在执行结束时,它会更新我们的数据库,因此无法运行同一脚本文件的两个副本(这将破坏我们的逻辑)。就像说 a.php 在下午 4 点触发,然后在下午 4 点 15 分,cron 将再次触发 a.php。这里我想检查a.php是否已完成执行,如果没有则跳过调用并通过检查相同的情况在下午4.30触发它,但b.php,c.php和a.php是并行运行的(但相同的实例可以't)。
答案1
标准做法是使用 pid 文件。每次执行脚本时,让它检查文件以查看它是否已在某处运行。操作顺序概述如下。
- 读取 pid
/var/run/yourscriptname.pid
- 检查pid是否正在运行,如果是则退出
- 获取你的pid,将其写入
/var/run/yourscriptname.pid
- 正常执行
- 删除pid文件
在您的情况下,这可以做到,但在某些情况下,脚本的调用速度可能足够快,以至于在检查 pid 和写入 pidfile 之间的时间内,另一个进程启动,也看不到 pidfile 并继续执行。您可以通过使用建议锁定进一步收紧事情。它是操作系统在几乎所有 Unix 上提供的功能。
参考:
- 男人群(2)
- 使用flock()锁定文件(PHP 语言)
答案2
这非常简单,通过flock
:
* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job
归功于这个答案。我是通过谷歌来到这里的,所以我也想在这里分享一下。
答案3
从你的问题中很难判断你是否想每次都开始一项新工作,或者如果它仍在运行则跳过轮换。
如果你想每次都重新开始,最简单的方法就是在killall your_command; your_command
你的 cron.
否则,请尝试pgrep you_command || your_command
在您的 cron 行中仅在未发现当前正在运行的情况下执行。
您还可以更花哨,在某种运行文件中注册作业的 PID,然后在开始工作之前检查该运行文件中是否有活动作业。如果你找到一个,你可以退出并让它运行,或者杀死另一个,并将你自己的 PID 标记为当前正在运行的 PID。