天天看點

php——實作linux的定時任務

  在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的地方引用該檔案,執行個體化類,新增定時任務就可以了。希望可以幫到大家,謝謝。