Laravel生产环境Cron Job多次执行问题排查求助
我将Laravel 8作为后端部署在EC2的Ubuntu服务器上,配置定时任务后出现同一Cron Job多次执行的情况:
- 最初的测试定时任务代码:
$schedule->call(function () { Log::info('function testing'); })->dailyAt('8:00')->timezone('Asia/Qatar');
该任务的日志被打印约39次。
- 添加
withoutOverlapping()后:
$schedule->call(function () { Log::info('function testing'); })->dailyAt('8:00') ->timezone('Asia/Qatar') ->name('unique_event_name') ->withoutOverlapping();
日志仍被打印约9次。
开发服务器使用相同代码与类似环境,定时任务仅执行一次,运行正常。
服务器
crontab -e中的配置:
* * * * * cd backend_path && php artisan schedule:run >> /dev/null 2>&1
- 项目
Kernel.php完整内容:
<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; use Illuminate\Support\Facades\DB; use Mail; use Illuminate\Support\Facades\Log; class Kernel extends ConsoleKernel { /** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ 'App\Console\Commands\DatabaseBackUp' ]; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->call(function () { Log::info('function calling'); })->dailyAt('8:00') ->timezone('Asia/Qatar') ->name('unique_event_name') ->withoutOverlapping(); // scheduler for Data Base backup twice daily 3 AM and 15 PM $schedule->command('database:backup')->twiceDaily(3, 15); } /** * Register the commands for the application. * * @return void */ protected function commands() { $this->load(__DIR__.'/Commands'); require base_path('routes/console.php'); } }
另外,我在同一EC2实例中更换了项目根目录并删除了旧文件夹,这是否会影响Cron Job的功能?
检查多用户Cron配置:Ubuntu服务器不同用户(如root、www-data、个人登录用户)各自拥有独立crontab,若多个用户都配置了
php artisan schedule:run,会导致Laravel调度器被重复触发。执行以下命令查看所有用户的Cron任务:for user in $(cut -f1 -d: /etc/passwd); do echo $user; crontab -u $user -l; done发现多余配置后直接删除即可。
验证项目目录路径:更换根目录后,确认
crontab -e中的backend_path是新目录的绝对路径,而非旧路径。手动执行Cron中的命令测试是否正常:cd /完整绝对路径/backend_path && php artisan schedule:run同时检查是否残留旧目录的Cron配置。
清理Laravel调度锁文件:
withoutOverlapping()依赖存储在storage/framework/cache/data的锁文件,若权限异常或旧项目锁文件残留,会导致锁失效。执行以下命令清理:cd /你的项目路径 && rm -rf storage/framework/cache/data/*同时确保
storage目录权限正确:chown -R www-data:www-data storage chmod -R 775 storage检查Cron服务状态:确认Cron服务无多实例运行或异常重启:
sudo systemctl status cron若有异常,重启服务:
sudo systemctl restart cron校准服务器时区:Laravel任务指定了时区,但系统时区偏差可能导致触发时间混乱。执行
timedatectl查看系统时区,若与Asia/Qatar(UTC+3)不一致则修改:sudo timedatectl set-timezone Asia/Qatar
关于更换项目目录的影响:若新目录的Cron配置正确且旧目录已彻底删除,不会直接影响Cron功能,但如果旧目录的Cron配置未清理、或旧项目有残留后台进程,就可能导致重复执行,需确保旧配置和进程已清理。
内容的提问来源于stack exchange,提问作者aseel

