每5分钟运行一次PHP脚本并避免竞争条件

时间:2010-08-25 23:52:48

标签: php cron

我有一个需要每5分钟运行一次的php脚本。目前我正在使用一个cron作业来运行它(并且效果很好)但我的主机只允许最少15分钟的时间。

所以我的问题是,我可以使用访问者每5分钟触发一次php脚本的运行。我可以轻松记录上次运行的时间,并根据已用时间重新运行它。

但是,我担心比赛条件。重要的是,脚本每5分钟只运行一次

我的脚本大约需要60秒才能运行。在此期间它会写入几个文件。如果脚本多次运行,则会损坏文件。另外,如果我在10分钟内没有输入电阻,那么在下一个电阻到达时运行一次就可以了。

是否有一些标准方法可以完成此任务?

谢谢!

5 个答案:

答案 0 :(得分:6)

您是否考虑让脚本运行一个带sleep的无限循环,在迭代之间等待5分钟?

for (;;)
{
  perform_actions();
  sleep(300);
}

或者,您可以拥有一个文件(例如,is_running),并在最后发布的脚本开头处获取一个独占lock。至少这样你就不会做任何具有破坏性的事情。

您也可以将这两种解决方案结合起来。

$fp = fopen("is_running", "r+");

/* is it already running? */
if (! flock($fp, LOCK_EX | LOCK_NB)) return;

for (;;)
{
  perform_actions();
  sleep(300);
}

然后让cron工作每15分钟运行一次。如果进程仍在运行,它将会挽救,否则它将重新启动并每5分钟恢复一次。

答案 1 :(得分:4)

Lame回答蹩脚的情况(ISP,而不是海报)。安排12个cron作业,全部调用相同的脚本,每个小时运行一次,但是以不同的5分钟标记。

00 * * * * root echo "run at :00 of every hour"
05 * * * * root echo "run at :05 of every hour"
10 * * * * root echo "run at :10 of every hour"

等,直到:55。但我支持我的原始评论 - 找到一个新的ISP:)

答案 2 :(得分:1)

如果你不能做@Brandon建议的事情,我会建议接近这个,就像我在PHP中编写守护进程时所做的那样(不是最好的解决方案,但实际上我不得不这样做)。

在我的情况下,脚本也访问了一个(日志)文件并对其进行了处理,然后将结果插入到数据库中。因此,为了确保我没有同时运行两个文件,我创建了一个“状态”文件,在该文件中,脚本获取了一个锁,如果无法正常失败则无法执行此操作。

$fh = fopen('status_file', 'w');

/**
 * LOCK_NB is required because otherwise your script would stall until
 * a lock is aquired, queing a bunch of scripts.
 */
if(!flock($fh, LOCK_EX | LOCK_NB)) {
  exit 1; // our job is done here
}

答案 3 :(得分:0)

您可以使用The Fat Controller以5分钟的间隔运行脚本。与CRON不同,它保证从脚本的一个实例结束到另一个脚本实例启动的间隔。

答案 4 :(得分:0)

访问者是否可以启动此脚本的答案是肯定的。您可以在访问者进入页面时运行该脚本。您可能希望存储开始时间,但也需要存储它是否正在运行的属性。在尝试更新数据时,应避免任何冲突的可能性。我还为邮件警告添加了一个附加字段,如果运行时超出最大时间,则可以使用该字段。然后,您可以让脚本向您发送一条警告电子邮件,告知您的脚本已超出最长时间。我亲自将这些状态保存在数据库中,但它们也可以存储在文件中。