PHP本身是沒有定時功能的,PHP也不能多線程。PHP的定時任務功能必須通過和其他工具結合才能實現
linux 的腳本實現
使用方式 :
crontab filecrontab [ -u user ] [ -u user ] { -l | -r | -e }
crontab 是用來讓使用者在固定時間或固定間隔執行程式之用
使用crontab寫shell腳本,然后讓PHP調用shell,這個是利用linux的特性,應該還不算PHP自身語言的特性
00 * * * * lynx -dump https://www.yourdomain.com/script.php
第1列表示分鍾1~59 每分鍾用或者 */1表示,/n表示每n分鍾,例如*/8就是每8分鍾的意思,下面也是類推
第2列表示小時1~23(0表示0點)
第3列表示日期1~31
第4列表示月份1~12
第5列標識號星期0~6(0表示星期天)
意思就是說通過lynx訪問這個url。我們在使用中主要用到lynx、curl、wget來實現對url的遠程訪問,而如果要提高效率,直接用php去執行本地php文件是最佳選擇,例如:
00 */2 * * * /usr/local/bin/php /home/www/script.php
這條語句就可以在每2小時的0分鍾,通過linux內部php環境執行script.php,注意,這里可不是通過url訪問,通過服務器環境來執行哦,而是直接執行,因為繞過了服務器環境,所以效率當然要高很多。
PHP實現
ignore_user_abort(true);
通過url訪問這個php的時候,即使用戶把瀏覽器關掉(斷開連接)
https://segmentfault.com/a/1190000002955509
laravel的定時任務
在以前,開發者需要為每一個需要調度的任務編寫一個Cron條目,這是很讓人頭疼的事。你的任務調度不在源碼控制中,你必須使用SSH登錄到服務器然后添加這些Cron條目。
1開始
任務調度定義在app/Console/Kernel.php文件的schedule方法中,該方法中已經包含了一個示例。你可以自由地添加你需要的調度任務到Schedule對象。
你可以在App\Console\Kernel類的schedule方法中定義所有調度任務。
1在這個例子中,我們將會在每天午夜調度一個被調用的閉包。在這個閉包中我們將會執行一個數據庫查詢來清空表:
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
DB::table('recent_users')->delete();
})->daily();
}
2除了調度閉包調用外,還可以調度Artisan命令和操作系統命令。例如,可以使用command方法通過命令名或類來調度一個Artisan命令:
$schedule->command('emails:send --force')->daily();
$schedule->command(EmailsCommand::class, ['--force'])->daily();
3exec命令可用於發送命令到操作系統:
$schedule->exec('node /home/forge/script.js')->daily();
2調用
開啟調度器
下面是你唯一需要添加到服務器的Cron條目,如果你不知道如何添加Cron條目到服務器,可以考慮使用諸如Laravel Forge這樣的服務來為管理Cron條目:
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1
該Cron將會每分鍾調用一次Laravel命令調度器,然后,Laravel評估你的調度任務並運行到期的任務。
3細節
調度常用選項
當然,你可以分配多種調度到任務:
方法描述
->cron('* * * * *'); 在自定義Cron調度上運行任務
->everyMinute(); 每分鍾運行一次任務
->everyFiveMinutes(); 每五分鍾運行一次任務
->everyTenMinutes(); 每十分鍾運行一次任務
->everyThirtyMinutes(); 每三十分鍾運行一次任務
->hourly(); 每小時運行一次任務
->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'); 設置時區
$schedule->call(function () {
// 每周星期一13:00運行一次...
})->weekly()->mondays()->at('13:00');
// Run hourly from 8 AM to 5 PM on weekdays...
$schedule->command('foo')
->weekdays()
->hourly()
->timezone('America/Chicago')
->between('8:00', '17:00');
->weekdays(); 只在工作日運行任務
->sundays(); 每個星期天運行任務
->mondays(); 每個星期一運行任務
->tuesdays(); 每個星期二運行任務
->wednesdays(); 每個星期三運行任務
->thursdays(); 每個星期四運行任務
->fridays(); 每個星期五運行任務
->saturdays(); 每個星期六運行任務
->between($start, $end); 基於特定時間段運行任務
->when(Closure); 基於特定測試運行任務
真理測試的約束條件
when方法用於限制任務基於給定真理測試的結果執行。換句話說,如果給定閉包返回true,只要沒有其它約束條件阻止任務運行,該任務就會執行:
$schedule->command('emails:send')->daily()->when(function () {
return true;
});
skip方法和when相反,如果skip方法返回true,調度任務將不會執行:
$schedule->command('emails:send')->daily()->skip(function () {
return true;
});
4避免任務重疊
默認情況下,即使前一個任務仍然在運行調度任務也會運行,要避免這樣的情況,可使用withoutOverlapping方法:
$schedule->command('emails:send')->withoutOverlapping();
在本例中,Artisan命令emails:send每分鍾都會運行,如果該命令沒有在運行的話。如果你的任務在執行時經常大幅度的變化,那么withoutOverlapping方法就非常有用,你不必再去預測給定任務到底要消耗多長時間。
5結果
任務輸出
Laravel調度器為處理調度任務輸出提供了多個方便的方法。首先,使用sendOutputTo方法,你可以發送輸出到文件以便稍后檢查:
$schedule->command('emails:send')
->daily()
->sendOutputTo($filePath);
如果你想要追加輸出到給定文件,可以使用appendOutputTo方法:
$schedule->command('emails:send')
->daily()
->appendOutputTo($filePath);
使用emailOutputTo方法,你可以將輸出發送到電子郵件,注意輸出必須首先通過sendOutputTo方法發送到文件。還有,使用電子郵件發送任務輸出之前,應該配置Laravel的電子郵件服務:
$schedule->command('foo')
->daily()
->sendOutputTo($filePath)
->emailOutputTo('foo@example.com');
注:emailOutputTo和sendOutputTo方法只對command方法有效,不支持call方法。
6任務鈎子
1使用before和after方法,你可以指定在調度任務完成之前和之后要執行的代碼:
$schedule->command('emails:send')
->daily()
->before(function () {
// Task is about to start...
})
->after(function () {
// Task is complete...
});
2ping URL
使用pingBefore和thenPing方法,調度器可以在任務完成之前和之后自動ping給定的URL。該方法在通知外部服務時很有用,例如Laravel Envoyer,在調度任務開始或完成的時候:
$schedule->command('emails:send')
->daily()
->pingBefore($url)
->thenPing($url);
使用pingBefore($url)或thenPing($url)特性需要安裝HTTP庫Guzzle,可以使用Composer包管理器來安裝Guzzle到項目: