【问题标题】:Running a Cron job continuously连续运行 Cron 作业
【发布时间】:2015-09-21 16:36:38
【问题描述】:

很抱歉,如果之前有人问过这个问题,但是我在搜索时找不到任何相关内容。

我目前有一个 PHP 脚本,它轮询数据库以获取下一条尚未更新的记录。我的问题是:如果我随后更新数据库以显示记录正在处理,而 cron 作业正在运行(大约需要 30 秒),并且 cron 作业设置为每秒运行一次,则 cron 作业在第 1 秒运行,但该作业会在 cron 作业第二次运行之前等待完成,还是会在第二次 2 运行?

谢谢

【问题讨论】:

  • 一个 cron 计划的最短时间肯定是一分钟吗?
  • 不,cron 作业将按计划运行,如果它们重叠,则由您的代码来处理事情,cron 不关心之前的作业是否仍在运行
  • 可能有更好的方法来完成我想要做的事情 - 我正在构建一个拥有多个用户的系统,每个用户都有一个在线销售渠道,例如亚马逊。我需要能够不断地轮询每个账户的订单,最好是同时轮询,但是如果其中一个账户有大量订单并且需要超过一分钟才能返回我的所有数据页面脚本,我不希望所有其他帐户在下载该帐户的订单时停止轮询,如果这有意义吗?
  • 没问题,安排 cron 作业“选择、更新”下一个可用的“订单”。将其标记为正在处理并将其提交到数据库。然后处理订单。下一个cron job 会找到一个新订单或者什么都没有。
  • 是的,这就是我正在考虑做的事情,所以每个帐户都会处于待处理状态,然后处理,然后完成,所以它第一次运行时会发现用户 1 处于待处理状态,并将其更改为正在处理。第二次它会发现用户 2 为待处理,因为用户 1 当前正在处理,等等。

标签: php cron


【解决方案1】:

如果您正在使用 cronjob 并且未在 php 脚本中使用任何类型的锁定,如果时间事件发生在最后一个脚本完成之前,cron 将运行多个脚本副本。

为避免此类问题,您可以执行以下操作:

$LOCK_FN = "/tmp/my-script.lock"
if(file_exists ($LOCK_FN)){
    //previous script is not finish exit.
    die("Previous script is not finished yet.");
}
//Create lock
$fp = fopen($LOCK_FN,"w");
fclose($fp);

/*

 Put your script logic here
 */

//Open the lock work is done.
unlink($LOCK_FN)

【讨论】:

  • 好的,非常感谢,所以如果第二个 cron 作业在第一个 cron 作业完成之前运行,我假设它不会中止第一个 cron 作业? (这其实是我想要发生的,我需要它持续处理下一条记录,即使上一条记录还没有完成)。
  • @MikeBowyer 它可能会也可能不会影响第一份工作,具体取决于您在脚本中编写的处理类型和逻辑;但这对你的代码来说是个坏主意;我强烈建议您使用锁定。
  • 锁定有一个大问题,如果在脚本运行时由于任何原因脚本崩溃或服务器重新启动,则 cron 作业将永远不会再次运行,直到您手动删除锁定文件
【解决方案2】:

使用套接字锁定某些东西。因为如果脚本被终止,socket 端口会自动再次打开。

<?php
$port = 1080; // choose unused port
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!$sock) {
    exit;
}
socket_set_nonblock($sock);
if (!socket_bind($sock, "127.0.0.1", $port)) {
    exit;
}

while(1) { ... }
?>

每个脚本使用不同的端口。

使用 * * * * * 将此脚本添加到 Crontab

【讨论】:

    【解决方案3】:

    在启动新实例之前,cronjob 不会等待前一个任务完成。你想要的是一个守护进程,见Run php script as daemon process

    【讨论】:

      猜你喜欢
      • 2017-01-23
      • 2012-12-21
      • 1970-01-01
      • 2019-04-07
      • 2013-07-02
      • 2014-11-02
      • 1970-01-01
      相关资源
      最近更新 更多