0
user-people-family-house-home
>

【Laravel】Schedule 排程任務完整指南

本篇介紹如何在 Laravel 框架中,使用 Schedule 設定排程任務,讓指定的程式碼在特定時間自動執行。什麼是 ...

Posted by Roy on 2026-02-26 17:52:44
1 目前 1 人正在閱讀
|
| Views

本篇介紹如何在 Laravel 框架中,使用 Schedule 設定排程任務,讓指定的程式碼在特定時間自動執行。

什麼是 Laravel Schedule?

Laravel Schedule 是 Laravel 內建的排程系統,讓你可以直接在程式碼中定義任務與執行頻率,不需要手動編輯 Server 上的 Crontab。

常見使用情境:

  • 每日寄送報表 Email
  • 定期清除過期資料 / Log
  • 每小時同步第三方 API 資料
  • 定期產生快取

設定方式(Laravel 11)

Laravel 11 之後,排程直接定義在 routes/console.php

# routes/console.php
use Illuminate\Support\Facades\Schedule;

// 每分鐘執行一個 Artisan 指令
Schedule::command('report:daily')->dailyAt('08:00');

// 每小時執行一個 Job
Schedule::job(new SyncDataJob)->hourly();

// 每天凌晨清除過期 token
Schedule::command('sanctum:prune-expired --hours=24')->daily();

Laravel 10 以前,在 app/Console/Kernel.phpschedule() 方法中定義:

# app/Console/Kernel.php
protected function schedule(Schedule $schedule): void
{
    $schedule->command('report:daily')->dailyAt('08:00');
    $schedule->job(new SyncDataJob)->hourly();
    $schedule->command('cache:clear')->weekly();
}

建立自訂 Artisan Command

php artisan make:command SendDailyReport
# app/Console/Commands/SendDailyReport.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Jobs\SendReportEmailJob;

class SendDailyReport extends Command
{
    protected $signature = 'report:daily';
    protected $description = '寄送每日報表 Email';

    public function handle(): void
    {
        $this->info('開始寄送每日報表...');

        SendReportEmailJob::dispatch();

        $this->info('完成!');
    }
}

常用頻率設定

方法 說明
->everyMinute() 每分鐘
->everyFiveMinutes() 每 5 分鐘
->hourly() 每小時整點
->hourlyAt(30) 每小時第 30 分鐘
->daily() 每天凌晨 00:00
->dailyAt('08:00') 每天早上 08:00
->weekdays() 只在平日(週一至週五)
->weekly() 每週日 00:00
->weeklyOn(1, '08:00') 每週一 08:00
->monthly() 每月 1 號 00:00
->cron('0 8 * * 1-5') 自訂 Cron 表達式

進階條件控制

// 只在正式環境執行
Schedule::command('report:daily')
    ->dailyAt('08:00')
    ->environments('production');

// 避免重疊執行(前一次還沒跑完就不再啟動)
Schedule::command('sync:data')
    ->everyFiveMinutes()
    ->withoutOverlapping();

// 在背景執行(不阻塞排程器)
Schedule::command('sync:data')
    ->everyFiveMinutes()
    ->runInBackground();

// 執行失敗時發送 Email 通知
Schedule::command('report:daily')
    ->daily()
    ->emailOutputOnFailure('[email protected]');

// 自訂條件決定是否執行
Schedule::command('report:daily')
    ->daily()
    ->when(fn () => config('app.reports_enabled'));

Server 上設定 Crontab

Laravel Schedule 的觸發點只需要在 Server 上設定一條 Crontab,讓 Laravel 自行管理後續所有排程:

# 編輯 crontab
crontab -e

# 加入以下一行(每分鐘觸發 Laravel Schedule)
* * * * * cd /var/www/html/your-project && php artisan schedule:run >> /dev/null 2>&1

使用 Supervisor 管理 Schedule(Laravel 11+)

Laravel 11 新增了 schedule:work 指令,可以讓排程在前景持續運行(每分鐘自動觸發),適合搭配 Supervisor 使用,不需要再設定 Crontab:

# /etc/supervisor/conf.d/schedule.conf
[program:schedule]
command=php /var/www/html/artisan schedule:work
numprocs=1
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/log/supervisor/schedule.log
supervisorctl reread
supervisorctl update
supervisorctl start schedule

本地測試

# 列出所有排程任務
php artisan schedule:list

# 立即觸發所有到期的排程(手動測試用)
php artisan schedule:run

# 持續運行排程(本地開發測試用,每分鐘自動觸發)
php artisan schedule:work

# 測試單一指令是否正常運作
php artisan report:daily

Crontab vs schedule:work 比較

方式 設定位置 最小單位 適合環境
Crontab Server crontab 1 分鐘 Laravel 10 以下或傳統部署
schedule:work + Supervisor Supervisor conf 1 分鐘 Laravel 11、Docker 環境

小結

Laravel Schedule 讓排程任務的管理完全集中在程式碼中,版本控制、部署一次搞定,不需要手動去每台伺服器設定 Crontab。搭配 Supervisor 的 schedule:work,在 Docker 環境下也能輕鬆讓排程穩定常駐運行。

參考文獻:

https://laravel.com/docs/11.x/scheduling

留言區

請先登入才能發表留言