Laravel提供了很是強勁的命令行工具(若是還不瞭解,傳送到第8往篇),咱們若是想要按期執行某個命令行,能夠利用crontab進行定時設置。若是有多個按期的任務,很簡單,咱們設定多條crontab規則在不一樣時間段內調度不一樣的命令便可。php
而Laravel框架內部也提供了這樣的調度機制。(固然,仍是逃不過crontab的支持)html
首先,咱們須要在crontab中添加這麼一條規則node
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
其次,全部的調度任務都在/app/Console/Kernel.php的schedule函數中進行調度設置redis
這個函數中能夠調度閉包、可調用對象(包含__invoke的對象)、artisian命令、列隊任務以及shell命令。如下以例子進行說明:shell
//調度閉包,->daily()即調度選項,天天凌晨零點運行任務 //關於調度選項後面會統一說明 $schedule->call(function () { DB::table('recent_users')->delete(); })->daily(); //調度可調用對象 //DeleteRecentUsers類中包含了__invoke魔術方法 $schedule->call(new DeleteRecentUsers)->daily(); //調度artisian命令 $schedule->command('emails:send --force')->daily(); $schedule->command(EmailsCommand::class, ['--force'])->daily(); //調度列隊任務 $schedule->job(new Heartbeat)->everyFiveMinutes(); $schedule->job(new Heartbeat, 'heartbeats')->everyFiveMinutes(); //將job投遞到heartbeats列隊中 //調度shell命令 $schedule->exec('node /home/forge/script.js')->daily();
經常使用的調度選項:編程
方法 | 描述 |
->cron('* * * * *'); | 在自定義Cron調度上運行任務 |
->everyMinute(); | 每分鐘運行一次任務 |
->everyFiveMinutes(); | 每五分鐘運行一次任務 |
->everyTenMinutes(); | 每十分鐘運行一次任務 |
->everyFifteenMinutes(); | 每十五分鐘運行一次任務 |
->everyThirtyMinutes(); | 每三十分鐘運行一次任務 |
->hourly(); | 每小時運行一次任務 |
->hourlyAt(17); | 每小時第十七分鐘運行一次任務 |
->daily(); | 天天凌晨零點運行任務 |
->dailyAt('13:00'); | 天天13:00運行任務 |
->twiceDaily(1, 13); | 天天1:00 & 13:00運行任務 |
->weekly(); | 每週運行一次任務 |
->monthly(); | 每個月運行一次任務 |
->monthlyOn(4, '15:00'); | 每個月4號15:00運行一次任務 |
->quarterly(); | 每一個季度運行一次 |
->yearly(); | 每一年運行一次 |
->timezone('America/New_York'); | 設置時區 |
額外調度約束選項:閉包
方法 | 描述 |
->weekdays(); | 只在工做日運行任務 |
->weekends(); | 只在週末運行任務 |
->sundays(); | 每一個星期天運行任務 |
->mondays(); | 每一個星期一運行任務 |
->tuesdays(); | 每一個星期二運行任務 |
->wednesdays(); | 每一個星期三運行任務 |
->thursdays(); | 每一個星期四運行任務 |
->fridays(); | 每一個星期五運行任務 |
->saturdays(); | 每一個星期六運行任務 |
->between($start, $end); | 基於特定時間段運行任務 |
->when(Closure); | 基於特定測試運行任務 |
->environments($env); | 只在指定環境運行任務 |
舉幾個例子:app
// 每週星期一13:00運行一次... $schedule->call(function () { })->weekly()->mondays()->at('13:00'); // 工做日的上午8點到下午5點每小時運行... $schedule->command('foo') ->weekdays() ->hourly() ->timezone('America/Chicago') ->between('8:00', '17:00'); //天天7點到22點之間,每小時運行 $schedule->command('reminders:send') ->hourly() ->between('7:00', '22:00'); //天天23點到4點以外的時間內,每小時運行 $schedule->command('reminders:send') ->hourly() ->unlessBetween('23:00', '4:00'); //when的閉包返回true時運行 $schedule->command('emails:send')->daily()->when(function () { return true; }); //skip的閉包返回false時運行 $schedule->command('emails:send')->daily()->skip(function () { return true; });
第三,任務調度的重疊處理框架
當下一次任務開始執行時,萬一上一次的任務尚未執行完成,新的任務是會執行的。也就是說,有可能出現屢次任務重疊執行的狀況。less
爲了不這種狀況,咱們可使用外部的手段來加鎖,好比文件鎖flock,或者redis的setnx均可以。可是Laravel很是貼心,已經幫咱們準備了這樣的機制:
$schedule->command('emails:send')->withoutOverlapping(); //鎖默認24小時失效 $schedule->command('emails:send')->withoutOverlapping(10); //鎖10分鐘失效
第四,任務調度的順序
默認狀況下,同時調度的多個命令會順序執行。若是你有一些長時間運行的命令,將會致使隨後的命令在預期以後好久才能執行。若是你想要讓命令在後臺執行以便它們能夠同時運,可使用 runInBackground 方法來實現:
$schedule->command('analytics:report') ->daily() ->runInBackground();
第五,任務輸出
咱們能夠將任務中的輸出重定向覆蓋寫入或追加寫入文件中,便於問題的排查:
//覆蓋寫入 $schedule->command('emails:send') ->daily() ->sendOutputTo($filePath); //追加寫入 $schedule->command('emails:send') ->daily() ->appendOutputTo($filePath);
最後,任務鉤子
使用 before 和 after 方法,你能夠指定在調度任務完成以前和以後要執行的代碼:
$schedule->command('emails:send') ->daily() ->before(function () { // 任務即將開始... }) ->after(function () { // 任務已經完成... });
好了,Laravel話題到這裏正式結束了。關於Laravel還有一些知識點,若是想要深刻了解的小夥伴就去看官方文檔吧。
下週開始,博主會進入另外一個話題。至於要寫什麼,嗯,還沒想好,你們下週再見:)
--------------------------- 我是可愛的分割線 ----------------------------
最後博主借地宣傳一下,漳州編程小組招新了,這是一個面向漳州青少年信息學/軟件設計的學習小組,有意向的同窗點擊連接,聯繫我吧。