You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel生产环境Cron Job多次执行问题排查求助

问题描述

我将Laravel 8作为后端部署在EC2的Ubuntu服务器上,配置定时任务后出现同一Cron Job多次执行的情况:

  1. 最初的测试定时任务代码:
$schedule->call(function () {
    Log::info('function testing');
})->dailyAt('8:00')->timezone('Asia/Qatar');

该任务的日志被打印约39次。

  1. 添加withoutOverlapping()后:
$schedule->call(function () {
    Log::info('function testing');
})->dailyAt('8:00')
  ->timezone('Asia/Qatar')
  ->name('unique_event_name')
  ->withoutOverlapping();

日志仍被打印约9次。

  1. 开发服务器使用相同代码与类似环境,定时任务仅执行一次,运行正常。

  2. 服务器crontab -e中的配置:

* * * * * cd backend_path && php artisan schedule:run >> /dev/null 2>&1
  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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:35:13