Roy-Try-Catch
← Back to list

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

Roy • Updated 2026-10-15 16:02:37

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

什麼是 Laravel Schedule?

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

Crontab 每分鐘跑 schedule:run,或 Supervisor 常駐 schedule:work,都會觸發 Laravel Schedule 執行到期任務,如 report:daily、SyncDataJob。

Crontab 或 Supervisor 兩種觸發方式,都由 Laravel 判斷哪些任務到期。

常見使用情境:

  • 每日寄送報表 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.php 的 schedule() 方法中定義:

# 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

常用頻率設定

方法 說明
->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'));

在伺服器上設定 Crontab

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

# 編輯 crontab
crontab -e

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

使用 Supervisor 管理 Schedule

schedule:work 指令(Laravel 8 起就有)可以讓排程在前景持續執行(每分鐘自動觸發),適合搭配 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 伺服器 crontab 1 分鐘 傳統主機部署
schedule:work + Supervisor Supervisor conf 1 分鐘 Docker/容器環境(Laravel 8+)

小結

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

參考文獻:

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

Comments

No comments yet.

請先登入