在 cron 作业 (Laravel) 中未触发循环时执行



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

你应该做的是有 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 作业

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

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

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

#!/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

最新更新