要求是设置每 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