【问题标题】:Do While Loop not triggered in cron job (Laravel) [closed]Do While Loop 未在 cron 作业中触发(Laravel)[关闭]
【发布时间】:2018-10-01 19:24:01
【问题描述】:

要求是设置一个每 4 秒运行一次的 cron 作业。由于 cron 作业只能在几分钟内执行,所以我决定每分钟触发一次我的作业,并在作业中运行几次。这是代码。

public function handle()
{

    $dt = Carbon::now();
    $counter = 60/4; //run the job every 4 seconds
    do {
        //logic goes here
        // add data to database
        time_sleep_until($dt->addSeconds(4)->timestamp);
    } while ($counter-- > 0);
}

Cron 作业安排在 crontab -e 中

*/1 * * * * /usr/bin/php /var/www/html/dashboard/artisan cronjob:pulldata

当我使用 php artisan 命令手动执行作业时,作业每 4 秒运行一次。但是,当它被 crontab -e 的 cronjob 触发时,它每分钟只执行一次。

【问题讨论】:

  • 您查看的是 crontab 日志还是 4 秒任务的实际结果?因为 crontab 只会每 60 秒显示一个新条目。
  • 嗨,这是一个函数,你不显示是否/如何调用它。它还调用了一个你没有显示的函数。请记住,您必须在问题中添加一些上下文,否则对我们来说这仍然是一个谜
  • @MarkWalet,函数内部的逻辑是将条目添加到数据库中的表中。一分钟内必须有 15 个条目(每 4 秒),但只有 1 个条目,这意味着作业只执行了一次。如果我使用 artisan 命令手动运行它,表中有 15 个条目。
  • 要改善您的 SO 体验,请阅读如何询问 On Topic questionQuestion Check listthe perfect question 以及如何创建 Minimal, Complete and Verifiable Example
  • @RiggsFolly,逻辑是向表中添加数据。将更新问题。并且从服务器调用 cron 作业 (crontab -e)。除此之外没有其他上下文

标签: php laravel laravel-5 cron


【解决方案1】:

你应该做的是有 15 个 cron 作业,每分钟运行一次,第一个偏移 0 秒,下一个偏移 4 秒、8 秒、12 秒等等

* * * * * /path/to/executable param1 param2
* * * * * ( sleep 4; /path/to/executable param1 param2 )
* * * * * ( sleep 8; /path/to/executable param1 param2 )
...

或者有一个将(command && sleep 4) & 链接 15 次的 cron 作业

【讨论】:

    【解决方案2】:

    我会这样做,因为您每分钟都启动 cron 作业,所以您必须考虑到您的实际数据库逻辑从每次迭代的 1 分钟中占用的时间,以防止重叠:

    public function handle() 
    {
        $minute = 60;
    
        do {
           $start = microtime(true);
    
           // Your Database Logic
    
           $end = microtime(true);
    
           sleep(4); 
    
           $minute = $minute - (4 + (($end - $start) / 60));
    
        } while ($minute > 0);
    }
    

    此外,您应该考虑将其作为后台进程运行一次,您可以通过在控制台调用 php artisan your:command & 中添加与符号来实现,然后您可以像这样编写它,但一定要清理每个逻辑中不必要的变量,以防止高内存消耗:

    public function handle() 
    {
         try {
             $this->process();
         } catch (\Exception $e) {
           // Log your error somewhere
           Log::error($e->getMessage());
    
           // Re-run process
           $this->process();
         }
    }
    
    protected function process() 
    {
        while(true) {
             // Your Database Logic
             sleep(4);
         }
    }
    

    【讨论】:

    • 这不是问题所在。 Dilani 遇到了一个“错误”,循环确实每 4 秒执行一次代码,持续一分钟,但是当使用 cronjob 调用时,它不是。这只是分配 4 秒调用的一种更奇特的方式。
    • 我的回复提供了一种没有 cron 表的替代方法,您应该已经阅读了整个回复。
    【解决方案3】:

    我不知道到底出了什么问题。但是其中一个问题可能是您的服务器阻止了持续执行 1 分钟的脚本。有办法解决这个问题。

    您可以做的是创建一个单独的 bash 脚本,每隔 x 秒调用一次您的工匠命令。就像this Ubuntu answer中建议的那样

    #!/bin/bash
    
    while true; do
      /usr/bin/php /var/www/html/dashboard/artisan cronjob:pulldata
      sleep 4;
    done
    

    然后在你的 cronjob 中调用这个脚本:

    */1 * * * * /var/www/html/dashboard/your-command.sh
    

    【讨论】:

    • 当您的第一句话是“我不知道到底出了什么问题”时,您拒绝了我的回答,说她的问题是关于错误的,然后进一步了解您的偏好。你自己没有为讨论增加任何价值。此外,在回答问题时,您应该提供示例,而不仅仅是链接。
    • 你是对的。我编辑了我的答案
    猜你喜欢
    • 2014-11-26
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    • 2017-07-26
    • 2014-06-30
    • 2012-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多