在php學習和工作生活中,經常需要定時去執行任務,一般可以分為純代碼實作和借助linux的定時任務管理器cron.d或者crontab來實作。
1.先來說一下純代碼是如何實作的。
<?php
ignore_user_abort();//關閉浏覽器仍然執行
set_time_limit(0);//讓程式一直執行下去
$interval=3;//每隔一定時間運作 3代表3s
do{
$msg=date("Y-m-d H:i:s");
file_put_contents("log.log",$msg,FILE_APPEND);//記錄日志
sleep($interval);//等待時間,進行下一次操作。
}while(true);
?>
這是一個基本的定時器,但是這個定時器有一個缺陷,因為while的判定條件是true,一旦這個程式執行就不可控制了,除非重新開機伺服器或者關機,非常麻煩。現在可以加入一個控制條件,來控制這個定時器的開與關。
建立一個controller.php
<?php
return 1;//1執行腳本 0退出執行腳本
?>
定時器timer.php改為
<?php
ignore_user_abort();//關閉浏覽器後,繼續執行php代碼
set_time_limit(0);//程式執行時間無限制
$sleep_time = 5;//多長時間執行一次
$switch = include 'switch.php';
while($switch){
$switch = include 'switch.php';
$msg=date("Y-m-d H:i:s").$switch;
file_put_contents("log.log",$msg,FILE_APPEND);//記錄日志
sleep($sleep_time);//等待時間,進行下一次操作。
}
exit();
?>
這就是純代碼實作定時任務的基本方法了,但是存在局限性。現在再來介紹一下linux的定時任務管理器,cron.d或者crontab。
2.cron.d增加定時任務
當我們要增加全局性的計劃任務時,一種方式是直接修改/etc/crontab。但是,一般不建議這樣做,/etc/cron.d目錄就是為了解決這種問題而建立的。
例如,增加一項定時的備份任務,我們可以這樣處理:在/etc/cron.d目錄下建立檔案backup.sh,内容如下:
# m h dom mon dow user command
* 1 * * * root /sbin/mon_zetc_logtar.sh
cron程序執行時,就會自動掃描該目錄下的所有檔案,按照檔案中的時間設定執行後面的指令。
cron執行時,也就是要讀取三個地方的配置檔案:一是/etc/crontab,二是/etc/cron.d目錄下的所有檔案,三是每個使用者的配置檔案。
是以在我們就可以使用php代碼中在/etc/cron.d目錄下建立*.sh檔案,然後将定時任務寫入*.sh檔案中,這樣就完成了cron.d增加定時任務。
3.crontab增加定時任務
一般,使用crontab -e指令來編輯定時任務清單,将定時任務寫入清單中。
如何用php代碼設定crontab,具體看下面代碼例子。
<?php
/*
Filename: PhpCrontab.php
Comment: php 控制linux crontab 指令
User: lxd
Time: 15/11/13 13:55
*/
class PhpCrontab {
private $_crontab_obj = null;
//構造 引入 是放在同一個目錄裡面的
public function __construct() {
set_include_path(get_include_path() . PATH_SEPARATOR . __DIR__);
spl_autoload_register(function($class_name) {
//需要将引入的檔案全部小寫
spl_autoload($class_name,'.php');
});
$this->_crontab_obj = new CrontabManager();
}
/*
* 新增任務
* @param id 任務唯一标示符,自己資料庫的,友善自己後期處理
* @param time 任務執行時間
* @param job 任務具體内容
*
* @return false | 任務自身的id标志
*/
public function addJob($id,$time,$job) {
//新增任務
$job_obj = $this->_crontab_obj->newJob();
$job_obj->on($time)->addComments(array($id))->doJob($job);
$this->_crontab_obj->add($job_obj);
$this->_crontab_obj->save();
$job_obj = $time = null;
//擷取任務清單
$job_arr = $this->getJobList();
//通過$id 找到任務的自身id
foreach($job_arr as $k => $v) {
//正則比對
$pattern = '/#\s[\w]+(\s|$)/iU';
$match_info = array();
$is_match = preg_match_all($pattern,$v,$match_info);
if(!$is_match)
return false;
if(trim($match_info[0][0]) == '# ' . $id)
return str_replace("\n",'',$match_info[0][1]);
}
return false;
}
/*
* 擷取任務清單
* @param void
* @return array
*/
public function getJobList() {
//擷取字元串任務清單
$job_str = $this->_crontab_obj->listJobs();
//解析為數組,傳回
return explode("\n\n",$job_str);
}
/*
* 清理一條任務
* @param 任務自身的id
* @return true | false
*/
function deleteJob($job = null) {
$jobsDeleted = 0;
if (!is_null($job)) {
$data = array();
$oldJobs = explode("\n", $this->listJobs()); // get the old jobs
if (is_array($oldJobs)) {
//放置comment 資訊
$_comment = '';
foreach ($oldJobs as $oldJob) {
if ($oldJob != '') {
//加入判斷,比對出comment資訊
if(preg_match_all('/^#(.*)/',$oldJob,$match_arr)) {
$_comment = $match_arr[0][0];
continue;
}
if (!preg_match('/' . $job . '/', $oldJob)) {
$newJob = new CronEntry($oldJob, $this);
$newJob->lineComment = '';
//設定comment 資訊
$newJob->comments = array($_comment);
$_comment = '';
$data[] = $newJob;
} else {
$jobsDeleted++;
}
}
}
}
$this->jobs = $data;
}
return $jobsDeleted;
}
/*
* 析構
*/
public function destruct() {
$this->_crontab_obj = null;
}
}
然後在需要操作crontab的地方引用該檔案,執行個體化類,新增定時任務就可以了。希望可以幫到大家,謝謝。