• 歡迎訪問奇跡の海網站,本站不上傳任何資源,所有資源均來自于網絡,歡迎加入奇跡の海~!奇跡の海-WordPress QQ群
  • 本站下載資源為網絡上收集整理而來,并且以計算機技術研究交流為目的,版權歸原作者所有,僅供大家參考,學習,不存在任何商業目的與商業用途.
  • 本站系統鏡像均來自于官方原版,ed2k可視為P2P下載鏈接。所有操作系統默認均為試用版,如有正版密鑰可以有效激活,本站不提供任何激活和相關服務。

PHP代碼實現定時任務(非linux-shell方式,與操作系統無關)

WEB服務 奇跡の海 2年前 (2017-08-22) 460次瀏覽 已收錄 0個評論 掃描二維碼

頁面交互效果

下面是寫好的示例前端交互頁面,主要是列表頁面,編輯頁面。

主要交互有:

1 開啟定時任務進程
2 關閉定時任務進程
3 新增一項定時任務
4 編輯已有的定時任務
5 刪除定時任務
6 開始一項定時任務
7 停止一項定時任務

定時任務分兩種:

1 執行一次
2 循環執行

定時任務執行的內容:

定時任務執行的內容其實還是一個http請求。 通過定時的方式,指定時間執行或者循執行。

1 列表頁面

PHP代碼實現定時任務(非linux-shell方式,與操作系統無關)

2 新建\編輯頁面

PHP代碼實現定時任務(非linux-shell方式,與操作系統無關)

代碼地址,演示地址

示例代碼是基于Laravel,Alpaca-spa框架編寫,并且作為 ‘Alpaca-Spa-Laravel后臺管理平臺’的一個模塊兒集成于系統中。

代碼 :?http://git.oschina.net/cc-sponge/Alpaca-Spa-Laravel

代碼 :?https://github.com/big-sponge/Alpaca-Spa-Laravel

Alpaca-Spa-Laravel :?http://full.tkc8.com

Alpaca-Spa :?http://www.tkc8.com

適用范圍

定時精確時間不低于1秒。web服務重啟、或者php重啟。該定時任務不會自動重啟。

實現原理

用PHP實現定時任務(非linux-shell方式,與操作系統平臺無關),主要兩個技術點:

1)PHP后臺進程
2)PHP異步處理

1 PHP后臺進程

一般情況,用命令行可以開啟一個php后臺進程。而在瀏覽器中通過HTTP請求一個php處理,會因為瀏覽器關閉,或者請求超時,使得后臺的php處理中斷。但是php提供了兩個方法可以會忽略瀏覽器關閉、請求超時:

ignore_user_abort(true);???? // 忽略客戶端斷開
set_time_limit(0);?????????? // 設置執行不超時

因此,我們可以使用這兩個函數從瀏覽器以HTTP請求的方式開啟一個php后臺進程。

2 PHP異步處理

php語言本身沒有可以跨平臺好用異步處理方法,但是可以通過curl或者fsockopen創建一個請求來實現異步處理。這里我們用fsockopen方法實現:

$fp = fsockopen("$ip", $port, $errno, $errstr,1);
????????if (!$fp) {
????????????return 'worker error:'."$errstr ($errno)
\n";
????????} else {
????????????$out = "POST $url HTTP/1.1\r\n";
????????????$out .= "Host: $ip\r\n";
????????????$out .= "Content-Type:application/x-www-form-urlencoded; charset=UTF-8\r\n";
????????????$out .= "Content-Length: " . strlen($postData) . "\r\n";
????????????$out .= "Connection: close\r\n";
????????????$out .="\r\n";
????????????$out .=$postData;
????????????fputs($fp, $out);
????????????fclose($fp);
????????}

前臺交互控制器

為了在前端界面方便控制定時任務的開啟關閉,新增、編輯、刪除,查看執行狀態。 同時也可以添加權限控制。 主要有8個操作接口(下面是以Laravel 路由示例):

1 查看定時任務進程狀態
2 開始定時任務進程 3 停止定時任務進程
4 添加,或者編輯定時任務
5 設置定時任務狀態
6 獲取指定定時任務明細
7 刪除定時任務
8 獲取定時任務列表

/* crontab - status 查看定時任務守護進程狀態 */
Route::any('crontab/status', "[email protected]");
?
/* crontab - start 開始定時任務 */
Route::any('crontab/start', "[email protected]");
?
/* crontab - stop??停止定時任務守護進程*/
Route::any('crontab/stop', "[email protected]");
?
/* crontab - editTask??添加,或者編輯定時任務*/
Route::any('crontab/editTask', "[email protected]");
?
/* crontab - changeTaskStatus??設置定時任務狀態 */
Route::any('crontab/changeTaskStatus', "[email protected]");
?
/* crontab - getIndexTask??獲取指定定時任務 */
Route::any('crontab/getIndexTask', "[email protected]");
?
/* crontab - removeTask??刪除定時任務 */
Route::any('crontab/removeTask', "[email protected]");
?
/* crontab - listTask??獲取定時任務列表 */
Route::any('crontab/listTask', "[email protected]");

完整的類代碼如下:

<?php
?
namespace App\Modules\Manage\Controllers;
?
use Crontab\Library\Crontab\AlpacaCrontab;
use Crontab\Library\Crontab\AlpacaDaemon;
use Crontab\Library\Crontab\AlpacaWorker;
use App\Modules\Manage\Controllers\Base\BaseController;
use App\Common\Code;
use App\Common\Msg;
?
/**
* 定時任務管理控制器
* @author Chengcheng
* @date 2016-10-19 15:50:00
*/
class CrontabController extends BaseController
{
????/**
???? * 設置不需要登錄的的Action,不加Action前綴
???? * @author Chengcheng
???? * @date?? 2016年10月23日 20:39:25
???? * <a href='http://www.jobbole.com/members/wx1409399284'>@return</a> array
???? */
????protected function noLogin()
????{
????????return [];
????}
?
????/**
???? * 設置不需要權限驗證的Action,不加Action前綴
???? * @author Chengcheng
???? * @date?? 2016年10月23日 20:39:25
???? * <a href='http://www.jobbole.com/members/wx1409399284'>@return</a> array
???? */
????protected function noAuth()
????{
????????// 以下Action不需要角色權限
????????return [];
????}
?
????/**
???? * 查看定時任務守護進程狀態
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? */
????public function status()
????{
????????//查看守護進程狀態
????????$result['code'] = Code::SYSTEM_OK;
????????$result['msg']??= Msg::SYSTEM_OK;
????????$result['data'] = AlpacaDaemon::daemon()->status();
?
????????//返回結果
????????return $this->ajaxReturn($result);
????}
?
????/**
???? * 開始定時任務
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? */
????public function start()
????{
????????//異步開啟守護進程
????????$result['code'] = Code::SYSTEM_OK;
????????$result['msg']??= Msg::SYSTEM_OK;
????????$result['data'] = AlpacaWorker::worker()->action(['REQUEST_URI' => "/crontab/index/start"]);
?
????????//返回結果
????????return $this->ajaxReturn($result);
????}
?
????/**
???? * 停止定時任務守護進程
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? */
????public function stop()
????{
????????//停止守護進程
????????$result['code'] = Code::SYSTEM_OK;
????????$result['msg']??= Msg::SYSTEM_OK;
????????$result['data'] = AlpacaDaemon::daemon()->stop();
?
????????//返回結果
????????return $this->ajaxReturn($result);
????}
????/**
???? * 添加,或者編輯定時任務
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? */
????public function editTask()
????{
????????/*
???????? * 1 獲取輸入參數
???????? * BEGIN_TIME????????開始時間
???????? * END_TIME??????????結束時間
???????? * INTERVAL??????????時間間隔
???????? * NAME??????????????名稱
???????? * STATUS????????????狀態 1-ENABLED,?? 2-DISABLE
???????? * TASK_TYPE???????? 類型 1-ONCE,??????2-LOOP
???????? * ACTION????????????要執行的Action
???????? * INDEX???????????? 索引,null或者0時候,表示新建
???????? * */
????????$this->requestData['NAME']?????? = $this->input('NAME', null);
????????$this->requestData['BEGIN_TIME'] = $this->input('BEGIN_TIME', null);
????????$this->requestData['END_TIME']?? = $this->input('END_TIME', null);
????????$this->requestData['INTERVAL']?? = $this->input('INTERVAL', null);
????????$this->requestData['TASK_TYPE']??= $this->input('TASK_TYPE', '1');
????????$this->requestData['ACTION']???? = $this->input('ACTION', null);
????????$this->requestData['STATUS']???? = $this->input('STATUS', '2');
????????$this->requestData['INDEX']??????= $this->input('INDEX', null);
????????$this->requestData['LAST_TIME']??= $this->input('LAST_TIME', null);
?
????????//2 檢查參數
????????if (empty($this->requestData['BEGIN_TIME'])) {
????????????$result["code"] = Code::SYSTEM_PARAMETER_NULL;
????????????$result["msg"]??= sprintf(Msg::SYSTEM_PARAMETER_NULL, 'BEGIN_TIME');
????????????return $this->ajaxReturn($result);
????????}
????????if ($this->requestData['TASK_TYPE'] == 2 && empty($this->requestData['END_TIME'])) {
????????????$result["code"] = Code::SYSTEM_PARAMETER_NULL;
????????????$result["msg"]??= sprintf(Msg::SYSTEM_PARAMETER_NULL, 'END_TIME');
????????????return $this->ajaxReturn($result);
????????}
????????if (empty($this->requestData['ACTION'])) {
????????????$result["code"] = Code::SYSTEM_PARAMETER_NULL;
????????????$result["msg"]??= sprintf(Msg::SYSTEM_PARAMETER_NULL, 'ACTION');
????????????return $this->ajaxReturn($result);
????????}
????????if ($this->requestData['TASK_TYPE'] == 2 && empty($this->requestData['INTERVAL'])) {
????????????$result["code"] = Code::SYSTEM_PARAMETER_NULL;
????????????$result["msg"]??= sprintf(Msg::SYSTEM_PARAMETER_NULL, 'INTERVAL');
????????????return $this->ajaxReturn($result);
????????}
?
????????//3 設置結束時間
????????$now??????= date('Y-m-d H:i:s', time());
????????$nextTime = date('Y-m-d H:i:s', strtotime($this->requestData['INTERVAL'], strtotime($this->requestData['BEGIN_TIME'])));
????????if ($this->requestData['TASK_TYPE'] == "1" || strtotime($now) < strtotime($this->requestData['BEGIN_TIME'])) {
????????????$nextTime = $this->requestData['BEGIN_TIME'];
????????}
?
????????//4 創建任務
????????$task = array(
????????????'NAME'?????? => $this->requestData['NAME'],?????????? //NAME
????????????'STATUS'???? => $this->requestData['STATUS'],???????? // 1-ENABLED,?? 2-DISABLE
????????????'TYPE'?????? => $this->requestData['TASK_TYPE'],??????// 1-ONCE,??????2-LOOP
????????????'INTERVAL'?? => $this->requestData['INTERVAL'],?????? //year(年),month(月),hour(小時)minute(分),second(秒)
????????????'BEGIN_TIME' => $this->requestData['BEGIN_TIME'],???? //開始時間
????????????'NEXT_TIME'??=> $nextTime,????????????????????????????//下次執行時間
????????????'LAST_TIME'??=> $this->requestData['LAST_TIME'],??????//上次執行時間
????????????'ACTION'???? => $this->requestData['ACTION'],???????? //執行的ACTION
????????????'END_TIME'?? => $this->requestData['END_TIME'],?????? //截止時間2
????????);
?
????????//5 判斷是新建還是修改
????????if (empty($this->requestData['INDEX'])) {
????????????//新建
????????????$info = AlpacaCrontab::crontab()->addTask($task);
????????} else {
????????????$this->requestData['INDEX'] -= 1;
????????????$info = AlpacaCrontab::crontab()->editTask($this->requestData['INDEX'], $task);
????????}
?
????????//5 返回結果
????????$result['code'] = Code::SYSTEM_OK;
????????$result['msg']??= Msg::SYSTEM_OK;
????????$result['data'] = $info;
????????return $this->ajaxReturn($result);
????}
?
????/**
???? * 設置定時任務狀態
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? */
????public function changeTaskStatus()
????{
????????/*
???????? * 1 獲取輸入參數
???????? * STATUS????????????狀態 1-ENABLED,?? 2-DISABLE
???????? * INDEX???????????? 索引
???????? * */
????????$this->requestData['STATUS'] = $this->input('STATUS', '2');
????????$this->requestData['INDEX']??= $this->input('INDEX', null);
?
????????//2 檢查參數
????????if (empty($this->requestData['STATUS'])) {
????????????$result["code"] = Code::SYSTEM_PARAMETER_NULL;
????????????$result["msg"]??= sprintf(Msg::SYSTEM_PARAMETER_NULL, 'STATUS');
????????????return $this->ajaxReturn($result);
????????}
????????if (empty($this->requestData['INDEX'])) {
????????????$result["code"] = Code::SYSTEM_PARAMETER_NULL;
????????????$result["msg"]??= sprintf(Msg::SYSTEM_PARAMETER_NULL, 'INDEX');
????????????return $this->ajaxReturn($result);
????????}
?
????????//3 修改狀態
????????$this->requestData['INDEX'] -= 1;
????????$data = AlpacaCrontab::crontab()->editTaskStatus($this->requestData['INDEX'], $this->requestData['STATUS']);
?
????????//4 返回結果
????????$result['code'] = Code::SYSTEM_OK;
????????$result['msg']??= Msg::SYSTEM_OK;
????????$result['data'] = $data;
????????return $this->ajaxReturn($result);
????}
?
????/**
???? * 查找單條定時任務
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? */
????public function getIndexTask()
????{
????????/*
???????? * 1 獲取輸入參數
???????? * INDEX???????????? 索引
???????? * */
????????$this->requestData['INDEX'] = $this->input('INDEX', null);
?
????????//2 檢查參數
????????if (empty($this->requestData['INDEX'])) {
????????????$result["code"] = Code::SYSTEM_PARAMETER_NULL;
????????????$result["msg"]??= sprintf(Msg::SYSTEM_PARAMETER_NULL, 'INDEX');
????????????return $this->ajaxReturn($result);
????????}
?
????????//3 刪除
????????$this->requestData['INDEX'] -= 1;
????????$data = AlpacaCrontab::crontab()->getIndexTask($this->requestData['INDEX']);
?
????????//4 返回結果
????????$result['code'] = Code::SYSTEM_OK;
????????$result['msg']??= Msg::SYSTEM_OK;
????????$result['data'] = $data;
????????return $this->ajaxReturn($result);
????}
?
????/**
???? * 刪除定時任務
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? */
????public function removeTask()
????{
????????/*
???????? * 1 獲取輸入參數
???????? * INDEX???????????? 索引
???????? * */
????????$this->requestData['INDEX'] = $this->input('INDEX', null);
?
????????//2 檢查參數
????????if (empty($this->requestData['INDEX'])) {
????????????$result["code"] = Code::SYSTEM_PARAMETER_NULL;
????????????$result["msg"]??= sprintf(Msg::SYSTEM_PARAMETER_NULL, 'INDEX');
????????????return $this->ajaxReturn($result);
????????}
?
????????//3 刪除
????????$this->requestData['INDEX'] -= 1;
????????$data = AlpacaCrontab::crontab()->removeTask($this->requestData['INDEX']);
?
????????//4 返回結果
????????$result['code'] = Code::SYSTEM_OK;
????????$result['msg']??= Msg::SYSTEM_OK;
????????$result['data'] = $data;
????????return $this->ajaxReturn($result);
????}
?
????/**
???? * 查看定時任務列表
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? */
????public function listTask()
????{
????????//查找
????????$data['task']?? = AlpacaCrontab::crontab()->listTask();
????????$data['total']??= count($data['task']);
????????$data['status'] = AlpacaDaemon::daemon()->status();
?
????????//返回結果
????????$result['code'] = Code::SYSTEM_OK;
????????$result['msg']??= Msg::SYSTEM_OK;
????????$result['data'] = $data;
????????return $this->ajaxReturn($result);
????}
}

實現后臺進程類

使用 ignore_user_abort(true); set_time_limit(0); 可以從瀏覽器開啟一個php后臺進程。為了避免出現多個后臺進程,需要借助一個配置來標識該后臺進程是否已經啟動

{"code":"1001","message":"Stop at:2017-02-24 11:29:43"}

當code是1001時候,表示后臺進程未啟動,這時通過http請求開啟后臺進程時,正常啟動

當code是1000時候,表示后臺進程已經啟動,這時通過http請求開啟后臺進程時,不做任何操作,以為進程已經啟動

當開啟后臺進程的請求到達后臺時候,讀取配置文件,如果code是1001,則啟動進程,并且設置code為1000,保存配置文件。

當關閉后臺進程的請求到達后臺時候,讀取配置文件,設置code為1001,保存配置文件。

后臺進程在運行時候,每隔一秒讀取配置文件,判斷code狀態,如果是1001,則結束執行; 如果是1000,則繼續執行

完整類的代碼如下:

<?php ? namespace Crontab\Library\Crontab; /** * 守護進程 * @author Chengcheng * @date 2016年10月21日 17:04:44 */ class AlpacaDaemon { ????private $daemon_json = __DIR__ . '/deamon.json'; ? ????private static $instance; ? ????private $events = []; ? ????public static function daemon() ????{ ????????return self::getInstance(); ????} ? ????private static function getInstance() ????{ ????????if(!self::$instance){ ????????????self::$instance = new self(); ????????????self::$instance->daemon_json = base_path('storage') . '/crontab/deamon.json';
????????}
????????return self::$instance;
????}
?
????public function setDaemon($daemon_json)
????{
????????$this->daemon_json = $daemon_json;
????????return $this;
????}
?
????public function setEvents(array $events)
????{
????????$this->events = $events;
????????return $this;
????}
?
????public function status()
????{
????????$data = json_decode(file_get_contents($this->daemon_json),true);
????????if(empty($data)){
????????????$data = array();
????????}
????????return $data;
????}
?
????public function stop()
????{
????????$data =new \stdClass();
????????$data->code="1001";
????????$data->message="Stop at:".date("Y-m-d H:i:s" ,time());
????????file_put_contents($this->daemon_json,json_encode($data),LOCK_EX);
?
????????$result["result_code"] = "1";
????????$result["result_message"] = "操作成功";
????????return $result;
????}
?
????public function start()
????{
????????$data = json_decode(file_get_contents($this->daemon_json) , true);
????????if(empty($data)){
????????????$data['code']="1001";
????????}
?
????????if($data['code'] == "1000" ){
????????????//die("Error - exit,?? Already running !");
????????????return;
????????}
?
????????$data['code']="1000";
????????$data['message']="Start";
????????file_put_contents($this->daemon_json,json_encode($data),LOCK_EX);
?
????????ignore_user_abort(true);???? // 忽略客戶端斷開
????????set_time_limit(0);?????????? // 設置執行不超時
?
?
????????while(true){
????????????$data = json_decode(file_get_contents($this->daemon_json) , true);
????????????if(empty($data) || empty($data['code']) || $data['code'] == "1001" ){
????????????????break;
????????????}
?
????????????if(!empty($this->events)){
????????????????foreach ($this->events as $e){
????????????????????$e();
????????????????}
????????????}
?
????????????$data['message'] = date("Y-m-d H:i:s" ,time())." : Working ...";
????????????file_put_contents($this->daemon_json, json_encode($data), LOCK_EX);
????????????sleep(1);
????????}
????????$this->stop();
????}
}

實現異步處理的類

完整類的代碼如下:

&lt;?php ? namespace Crontab\Library\Crontab; class AlpacaWorker {???????? ????private static $instance; ? ????private $accessToken = ''; ? ????public static function worker() ????{ ????????return self::getInstance(); ????} ? ????private static function getInstance() ????{ ????????if(!self::$instance){ ????????????self::$instance = new self(); ????????????self::$instance-&gt;accessToken= 'VyKfohBbwlkTOqp2jvI<a href="http://www.bavghg.tw/archives/tag/wp" title="查看更多關于WP的文章" target="_blank">WP</a>W92';
????????}
????????return self::$instance;
????}
?
????public function action(array $worker = null)
????{
????????//獲取參數
????????$ip?? = empty($worker['SERVER_ADDR']) ? $_SERVER['SERVER_NAME'] : $worker['SERVER_ADDR'];???? //服務器IP地址
????????$port = empty($worker['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : $worker['SERVER_PORT'];???? //服務器端口
????????$url??= empty($worker['REQUEST_URI']) ? '/' :$worker['REQUEST_URI'];??????????????????????????//服務器URL
????????$data = empty($worker['REQUEST_DATA']) ? '' :$worker['REQUEST_DATA'];???????????????????????? //請求參數
?
????????//格式化請求參數
????????$postData = &quot;&quot;;
????????$needChar = false;
????????if(is_array($data)){
????????????foreach($data as $key =&gt; $val) {
????????????????$postData .= ($needChar ? &quot;&amp;&quot; : &quot;&quot;) . urlencode($key) . &quot;=&quot; . urlencode($val);
????????????????$needChar = true;
????????????}
????????}else{
????????????$postData = $data;
????????}
?
????????$url=$url.&quot;?accessToken=&quot;.$this-&gt;accessToken;
?
????????//使用fsockopen方式異步調用action
????????$fp = fsockopen(&quot;$ip&quot;, $port, $errno, $errstr,1);
????????if (!$fp) {
????????????return 'worker error:'.&quot;$errstr ($errno)
\n&quot;;
????????} else {
????????????$out = &quot;POST $url HTTP/1.1\r\n&quot;;
????????????$out .= &quot;Host: $ip\r\n&quot;;
????????????$out .= &quot;Content-Type:application/x-www-form-urlencoded; charset=UTF-8\r\n&quot;;
????????????$out .= &quot;Content-Length: &quot; . strlen($postData) . &quot;\r\n&quot;;
????????????$out .= &quot;Connection: close\r\n&quot;;
????????????$out .=&quot;\r\n&quot;;
????????????$out .=$postData;
????????????fputs($fp, $out);
????????????fclose($fp);
????????}??????
????????return 'worker success!';
????}
}

定時任務處理類

定時任務處理類 主要是實現新增、編輯、刪除定時任務,執行定時任務要處理的方法

定時任務的信息以json格式存放在下面的配置文件中

[{"NAME":"\u6d4b\u8bd5\u5b9a\u65f6\u4efb\u52a12","STATUS":"2","TYPE":"1","INTERVAL":"5 second","BEGIN_TIME":"2017-02-21 11:55:00","NEXT_TIME":"2017-02-21 11:55:00","LAST_TIME":null,"ACTION":"\/main\/crontab\/index2","END_TIME":"2017-02-10 15:55:00"},{"NAME":"TEST - log","STATUS":"2","TYPE":"2","INTERVAL":"5 second","BEGIN_TIME":"2017-08-10 09:00:53","NEXT_TIME":"2017-08-10 09:59:00","LAST_TIME":"2017-08-10 09:58:55","ACTION":"\/crontab\/task\/test","END_TIME":"2017-08-11 09:25:53"}]

主要的字段為:

INDEX 索引
BEGIN_TIME 開始時間
END_TIME 結束時間
INTERVAL 時間間隔
NAME 名稱
STATUS 狀態 1-ENABLED, 2-DISABLE
TASK_TYPE 類型 1-ONCE, 2-LOOP
ACTION 要執行的Action

類中主要有7個方法:

listTask() 查看定時任務列表 addTask() 添加定時任務 editTask() 編輯定時任務 editTaskStatus() 編輯定時任務狀態 getIndexTask() 獲取指定定時任務信息 removeTask() 刪除定時任務 doTask() 執行定時任務指定的任務

完整類的代碼如下:

<?php ? namespace Crontab\Library\Crontab; /** * 定時任務 * @author Chengcheng * @date 2016年10月21日 17:04:44 */ class AlpacaCrontab { ????//定時任務文件 ????private $task_json = __DIR__ .'/crontab.json'; ? ????//單例 ????private static $instance; ? ????//單例 ????public static function crontab() ????{ ????????return self::getInstance(); ????} ? ????//單例 ????private static function getInstance() ????{ ????????if(!self::$instance){ ????????????self::$instance = new self(); ????????????self::$instance->task_json = base_path('storage') . '/crontab/crontab.json';
????????}
????????return self::$instance;
????}
?
????/**
???? * 配置
???? * @author Chengcheng
???? * @param array $crontab
???? * @date 2016-10-23 20:34:00
???? * <a href='http://www.jobbole.com/members/wx1409399284'>@return</a> array
???? */
????public function setConfig($crontab)
????{
????????$this->task_json = $crontab;
????????return $this;
????}
?
????/**
???? * 查看定時任務
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? * <a href='http://www.jobbole.com/members/wx1409399284'>@return</a> array
???? */
????public function listTask()
????{
????????$tasks = json_decode(file_get_contents($this->task_json));
????????$i = 0;
????????foreach ($tasks as $task)
????????{
????????????$tasks[$i]->INTERVAL = $this->timeToStr($tasks[$i]->INTERVAL);
????????????$i++;
????????}
????????return $tasks;
????}
?
????/**
???? * 添加定時任務
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? * <a href='http://www.jobbole.com/members/wx1409399284'>@return</a> array
???? */
????public function addTask($task)
????{
????????$result["result_code"] = "1";
????????$result["result_message"] = "添加成功";
????????$tasks = json_decode(file_get_contents($this->task_json),true);
????????$tasks[count($tasks)] = $task;
????????file_put_contents($this->task_json, json_encode($tasks), LOCK_EX);
????????return $result;
????}
?
????/**
???? * 編輯定時任務
???? * @author Chengcheng
???? * @param string $index
???? * @param string $task
???? * @date 2016-10-23 20:34:00
???? * <a href='http://www.jobbole.com/members/wx1409399284'>@return</a> array
???? */
????public function editTask($index,$task)
????{
????????$result["result_code"] = "1";
????????$result["result_message"] = "修改成功";
????????$tasks = json_decode(file_get_contents($this->task_json));
????????$tasks[$index] = $task;
????????file_put_contents($this->task_json, json_encode($tasks), LOCK_EX);
????????return $result;
????}
?
????/**
???? * 編輯定時任務狀態
???? * @author Chengcheng
???? * @param string $index
???? * @param string $status
???? * @date 2016-10-23 20:34:00
???? * <a href='http://www.jobbole.com/members/wx1409399284'>@return</a> array
???? */
????public function editTaskStatus($index,$status)
????{
????????$result_data["result_code"] = "1";
????????$result_data["result_message"] = "修改狀態成功[".$status."]";
????????$tasks = json_decode(file_get_contents($this->task_json));
????????$tasks[$index]->STATUS = $status;
????????file_put_contents($this->task_json, json_encode($tasks), LOCK_EX);
????????return $result_data;
????}
?
????/**
???? * 獲取定時任務
???? * @author Chengcheng
???? * @param string $index
???? * @date 2016-10-23 20:34:00
???? * <a href='http://www.jobbole.com/members/wx1409399284'>@return</a> array
???? */
????public function getIndexTask($index)
????{
????????$result_data["result_code"] = "1";
????????$result_data["result_message"] = "獲取任務成功【".$index."】";
????????$tasks = json_decode(file_get_contents($this->task_json));
????????$result_data["result_data"] = $tasks[$index];
????????return $result_data;
????}
?
????/**
???? * 刪除定時任務
???? * @author Chengcheng
???? * @param string $index
???? * @date 2016-10-23 20:34:00
???? * <a href='http://www.jobbole.com/members/wx1409399284'>@return</a> array
???? */
????public function removeTask($index)
????{
????????$result_data["result_code"] = "1";
????????$result_data["result_message"] = "刪除任務【".$index."】成功";
????????$tasks = json_decode(file_get_contents($this->task_json));
????????array_splice($tasks, $index, 1);
????????file_put_contents($this->task_json, json_encode($tasks), LOCK_EX);
????????return $result_data;
????}
?
????/**
???? * 執行定時任務
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? * <a href='http://www.jobbole.com/members/wx1409399284'>@return</a> array
???? */
????public function doTask()
????{
????????$tasks = json_decode(file_get_contents($this->task_json) ,true);??????
????????if(empty($tasks)){ return ;}
?
????????$now = date('Y-m-d H:i:s',time());
????????foreach ($tasks as &$task){
????????????if(empty($task['STATUS']) || empty($task['TYPE'])??|| empty($task['BEGIN_TIME']) || empty($task['ACTION']) )
????????????{
????????????????continue;
????????????}
?
????????????if($task['STATUS'] != 1)
????????????{
????????????????continue;
????????????}
?
????????????if(!empty($task['END_TIME']) && strtotime($now)>=strtotime($task['END_TIME'])){
????????????????$task['NEXT_TIME']='END';
????????????????continue;
????????????}
?
????????????if($task['TYPE'] == 1 && empty($task['NEXT_TIME']) )
????????????{
????????????????continue;
????????????}
?
????????????if($task['TYPE'] == 2 && empty($task['INTERVAL']) )
????????????{
????????????????continue;
????????????}
?
????????????if(!empty($task['NEXT_TIME']) && $task['NEXT_TIME']=='END' )
????????????{
????????????????continue;
????????????}
?
????????????if($task['TYPE'] == 1 && (strtotime($now)>=strtotime($task['NEXT_TIME'])))
????????????{
????????????????$task['LAST_TIME']= $now;
????????????????$task['NEXT_TIME']='END';
????????????????$task['STATUS']=2;
????????????????AlpacaWorker::worker()->action(['REQUEST_URI'=>"{$task['ACTION']}"]);
????????????????continue;
????????????}
?
????????????if($task['TYPE'] == 2)
????????????{
????????????????if(empty($task['NEXT_TIME'])){
????????????????????$task['NEXT_TIME'] = $task['BEGIN_TIME'];
????????????????}
?
????????????????if(strtotime($now)>=strtotime($task['NEXT_TIME'])){
????????????????????$task['LAST_TIME']= $now;
????????????????????$task['NEXT_TIME']= date('Y-m-d H:i:s',strtotime($task['INTERVAL']));
????????????????????AlpacaWorker::worker()->action(['REQUEST_URI'=>"{$task['ACTION']}"]);
????????????????}
????????????????continue;
????????????}
????????}
?
????????file_put_contents($this->task_json, json_encode($tasks), LOCK_EX);
????????return $tasks;
????}
?
????/**
???? * 格式化時間
???? * @author Chengcheng
???? * @param string $interval
???? * @date 2016-10-23 20:34:00
???? * <a href='http://www.jobbole.com/members/wx1409399284'>@return</a> array
???? */
????private function timeToStr($interval)
????{
????????$result = "";
????????if($interval != null && $interval != ""){
????????????$temp = explode(" ", $interval);
????????????$iNumTemp = $temp[0];
????????????$iType = $temp[1];
????????????$iNum = str_replace("+", "", $iNumTemp);
????????????$str = "";
????????????switch ($iType){
????????????????case "year":
????????????????????$str = "(年)";
????????????????????break;
????????????????case "month":
????????????????????$str = "(月)";
????????????????????break;
????????????????case "day":
????????????????????$str = "(日)";
????????????????????break;
????????????????case "hour":
????????????????????$str = "(小時)";
????????????????????break;
????????????????case "minute":
????????????????????$str = "(分)";
????????????????????break;
????????????????case "second":
????????????????????$str = "(秒)";
????????????????????break;
????????????????default:
????????????????????break;
????????????}
?????????? $result = $iNum. $str;
????????}
????????return $result;
????}
}

定時任務進程入口控制器

主要是為了實現異步開啟后臺進程

<?php
?
namespace Crontab\Controllers;
?
use Crontab\Common\Code;
use Crontab\Common\Msg;
use Crontab\Controllers\Base\BaseController;
use Crontab\Library\Crontab\AlpacaCrontab;
use Crontab\Library\Crontab\AlpacaDaemon;
use Crontab\Library\Crontab\AlpacaWorker;
?
/**
* index
* @author Chengcheng
* @date 2017-02-22 15:50:00
*/
class IndexController extends BaseController
{
????/**
???? * 設置不需要登錄的的Action,不加Action前綴
???? * @author Chengcheng
???? * @date?? 2016年10月23日 20:39:25
???? * <a href='http://www.jobbole.com/members/wx1409399284'>@return</a> array
???? */
????protected function withoutLoginActions()
????{
?
????}
?
????/**
???? * 開始定時任務的守護進程
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? */
????public function start()
????{
?
????????//開始守護進程
????????$result['code'] = Code::SYSTEM_OK;
????????$result['msg']??= Msg::SYSTEM_OK;
?
????????//在守護進程中注入定時任務
????????$events = ['0'=>function(){
????????????AlpacaWorker::worker()->action(['REQUEST_URI'=>"/crontab/index/task"]);
????????}];
????????AlpacaDaemon::daemon()->setEvents($events);
????????AlpacaDaemon::daemon()->start();
?
????????//返回結果
????????return $this->ajaxReturn($result);
????}
?
????/**
???? * 停止定時任務的守護進程
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? */
????public function stop()
????{
????????//停止守護進程
????????$result['code'] = Code::SYSTEM_OK;
????????$result['msg']??= Msg::SYSTEM_OK;
????????$result['data'] = AlpacaDaemon::daemon()->stop();
?
????????//返回結果
????????return $this->ajaxReturn($result);
????}
?
????/**
???? * 執行定時任務
???? * @author Chengcheng
???? * @date 2016-10-23 20:34:00
???? */
????public function task()
????{
????????//執行定時任務
????????$result['code'] = Code::SYSTEM_OK;
????????$result['msg']??= Msg::SYSTEM_OK;
????????$result['data'] = AlpacaCrontab::crontab()->doTask();
?
????????//返回結果
????????return $this->ajaxReturn($result);
????}
}

以上是PHP實現定時任務的核心類與方法, 完整的代碼請參看代碼服務器中提供的源碼。


版權聲明:本站所有文章和資源使用CC BY-NC-SA 4.0協議授權發布 , 轉載應當以相同方式注明文章來自“SeaOMC.COM->PHP代碼實現定時任務(非linux-shell方式,與操作系統無關)!在下邊可以分享本文哦!
喜歡 (0)
[]
分享 (0)
奇跡の海
關于作者:
一個WordPress菜鳥!
發表我的評論
取消評論

表情 貼圖 加粗 刪除線 居中 斜體 簽到

Hi,您需要填寫昵稱和郵箱!

  • 昵稱 (必填)
  • 郵箱 (必填)
  • 網址
中国福利彩票36选7开奖结果