在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的地方引用该文件,实例化类,新增定时任务就可以了。希望可以帮到大家,谢谢。