在cron作业中未触发While循环(Laravel)

时间:2018-10-01 08:43:30

标签: php laravel laravel-5 cron

要求是设置一个每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触发时,它仅每分钟执行一次。

3 个答案:

答案 0 :(得分:1)

您应该做的是有15个cron作业,每个作业每分钟运行一次,第一个作业偏移零秒,第二个作业偏移4秒,8秒,12,依此类推

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

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

答案 1 :(得分:-1)

我不知道到底出了什么问题。但是问题之一可能是服务器无法阻止连续执行1分钟的脚本。有一种解决方法。

您可以做的是创建一个单独的bash脚本,该脚本每x秒调用一次artisan命令。就像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

答案 2 :(得分:-1)

我会这样做,因为您每分钟启动一次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);
     }
}