2010-08-25 126 views
6

我有一个php脚本,需要每5分钟运行一次。目前我使用的是一个cron作业来运行它(并且效果很好),但我的主机只允许15分钟的最短时间。每5分钟运行一次PHP脚本并避免竞争条件

所以我的问题是,我可以使用访客触发每5分钟运行一个PHP脚本。我可以很容易地记录它上次运行的时间,并根据经过的时间重新运行它。

但是,我很担心竞赛条件。剧本每5分钟一次只能运行一次,这一点很重要。

我的脚本需要大约60秒才能运行。它在这段时间写入一对夫妇的文件。如果脚本运行多次,将会损坏文件。另外,如果我在10分钟内没有获得访问者,那么当下一个访问者到达时运行一次就没有问题。

是否有一些标准的方法来完成这项任务?

谢谢!

+0

我不确定我是否理解这个问题。是否您的主机不允许cron作业比每15分钟更频繁地执行? – Icode4food 2010-08-25 23:57:32

+1

标准的方式是使用一个web主机,它不会对cron施加任何坏的,任意的规则。谁这么做? – Erik 2010-08-26 00:30:56

+1

切换主机。解决问题 – Stoosh 2010-08-26 00:31:55

回答

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分钟恢复一次更新。

+0

这似乎是一个好主意和一个相当不错的解决方案。我猜我需要调用php的set_time_limit。然后我希望我的主机不会自动杀死长时间运行的进程...但是,这似乎是我最好的选择。谢谢。 – Imbue 2010-08-26 01:16:39

+1

'set_time_limit'是您需要调整超时的功能。 http://php.net/manual/en/function.set-time-limit.php每次脚本运行时,我都会将它设置为330,这样你就不用担心了。 – Icode4food 2010-08-26 01:39:08

+1

为了让你们知道,主机允许我的脚本运行约。杀死它前26小时。不久之后,cron弹出另一个注意到文件已解锁并且我又恢复正常工作的文件。有一件事会吓倒我,如果主机在写入数据时杀死我的脚本,会发生什么情况。在这种情况下,数据可能会被破坏,直到cron有机会运行另一个脚本。换句话说,一年几次,我可能会服务大约5-10分钟的损坏数据。 – Imbue 2010-08-28 21:03:54

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 
} 
4

跛脚回答跛脚的情况(ISP,而不是海报)。 Schedule 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 :)

+1

我相信这会起作用,这可能是一个体面的解决方案,但我担心如果我的主机注意到它会发生什么。 – Imbue 2010-08-26 01:14:03

+3

@Imbue - 所以你认为你的主人会在无限循环中看起来更加善良? – 2010-08-26 01:36:50

+0

我认为一个花费在睡眠中几乎所有时间的无限循环将不那么明显,也许有点反抗。或不。很难说真的。 – Imbue 2010-08-26 02:32:53

0

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

+0

嗨我发送了一条评论在您的网站上询问有关TheFatController的事情,我的名字是'geocine' – 2011-07-04 16:54:31

0

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