分析入口文件main.php


在分析之前,需要了解php cli模式下的編程

1.了解getopt函數,php手冊地址:http://php.net/manual/zh/function.getopt.php

      static private $help = <<<EOF

  幫助信息:
  Usage: /path/to/php main.php [options] -- [args...]

  -h [--help]        顯示幫助信息
  -p [--pid]         指定pid文件位置(默認pid文件保存在當前目錄)
  -s start           啟動進程
  -s stop            停止進程
  -s restart         重啟進程
  -l [--log]         log文件夾的位置
  -c [--config]      config文件的位置
  -d [--daemon]      是否后台運行
  -r [--reload]      重新載入配置文件
  -m [--monitor]     監控進程是否在運行,如果在運行則不管,未運行則啟動進程
  --worker           開啟worker
  --tasktype         task任務獲取類型,[file|mysql] 默認是file
  --checktime        默認精確對時(如果精確對時,程序則會延時到分鍾開始0秒啟動) 值為false則不精確對時

EOF;
    /**
     * 運行入口
     */
    static public function run()
    {
        $opt = getopt(self::$options, self::$longopts);
        self::spl_autoload_register();
        self::params_h($opt);
        self::params_d($opt);
        self::params_p($opt);
        self::params_l($opt);
        self::params_c($opt);
        self::params_r($opt);
        self::params_worker($opt);
        self::params_tasktype($opt);
        self::params_checktime($opt);
        $opt = self::params_m($opt);
        self::params_s($opt);
    }

  如上,main.php 可以支持長短選項,以及接收參數

 

短選項是options 。該字符串中的每個字符會被當做選項字符,匹配傳入腳本的選項以單個連字符(-)開頭。 比如,一個選項字符串 "x" 識別了一個選項 -x。 只允許 a-z、A-Z 和 0-9。

長選項是longopts。此數組中的每個元素會被作為選項字符串,匹配了以兩個連字符(--)傳入到腳本的選項。 例如,長選項元素 "opt" 識別了一個選項 --opt

這里有一個條件非常重要

  • 單獨的字符(不接受值)
  • 后面跟隨冒號的字符(此選項需要值)
  • 后面跟隨兩個冒號的字符(此選項的值可選)

比如,我們試試看這個main.php -h 和 -s start 這里h是不帶值的,s是可以帶值的

<?php
$options = 's:h';
$xx = getopt($options);
var_dump($xx);

E:\FMS\trunk\swoole\study_swoole>php test.php -h

輸出:

E:\FMS\trunk\swoole\study_swoole\test.php:4:
array(1) {
'h' =>
bool(false)
}

E:\FMS\trunk\swoole\study_swoole>php test.php -s reload

輸出:
E:\FMS\trunk\swoole\study_swoole\test.php:4:
array(1) {
's' =>
string(6) "reload"
}

了解了,cli怎么獲取參數,我們再去看下main.php 的run方法到底在執行什么邏輯

45行:self::spl_autoload_register();自己添加了自己支持的自動引入

46行:self::params_h($opt); 返回幫助信息,並且會直接die退出

[root@localhost crontab]# php main.php -h

  幫助信息:
  Usage: /path/to/php main.php [options] -- [args...]

  -h [--help]        顯示幫助信息
  -p [--pid]         指定pid文件位置(默認pid文件保存在當前目錄)
  -s start           啟動進程
  -s stop            停止進程
  -s restart         重啟進程
  -l [--log]         log文件夾的位置
  -c [--config]      config文件的位置
  -d [--daemon]      是否后台運行
  -r [--reload]      重新載入配置文件
  -m [--monitor]     監控進程是否在運行,如果在運行則不管,未運行則啟動進程
  --worker           開啟worker
  --tasktype         task任務獲取類型,[file|mysql] 默認是file
  --checktime        默認精確對時(如果精確對時,程序則會延時到分鍾開始0秒啟動) 值為false則不精確對時

47行:self::params_d($opt);//設置常量,Crontab::$daemon = true; 設置為守護進程

48行:self::params_p($opt);//設置pid文件的位置 ,如果-p不接入參數會默認保存在當前目錄

        if (empty(Crontab::$pid_file)) {
            Crontab::$pid_file = ROOT_PATH . "/pid";
        }    

49行:self::params_l($opt);//設置日志文件放置位置,如果-l不寫參數會默認保存在當前目錄的logs文件夾

50行:self::params_c($opt);//設置config配置參數這里的配置參數太過於復雜,我也不認為有人會想輸入這個參數,這里默認值是根目錄下的config/crontab.php中

<?php
return array(
    'taskid1' =>
        array(
            'taskname' => 'php -i',  //任務名稱
            'rule' => '* * * * * *',//定時規則
            "unique" => 1, //排他數量,如果已經有這么多任務在執行,即使到了下一次執行時間,也不執行
            'execute'  => 'Cmd',//命令處理類
            'args' =>
                array(
                    'cmd'    => 'php -i',//命令
                    'ext' => '',//附加屬性
                ),
        ),
    'taskid2' =>
        array(
            'taskname' => 'test',  //任務名稱
            'rule' => array("09:30","14:12:58","22:30:36","22:24:36"),
            "unique" => 1, //排他數量,如果已經有這么多任務在執行,即使到了下一次執行時間,也不執行
            "execute" =>"Gather",
            'args' =>
                array(
                    'cmd'    => 'gather',//命令
                    'ext' => '',//附加屬性
                ),
        ),
);  

 這里是配置任務的相關參數,注意這里有幾個需要注意的,execute是需要執行的命令,unique排他數量,rule是規則

 行51:self::params_r($opt);

 這里會重新載入配置文件,會判斷之前的pid文件是否存在,如果存在就會執行kill

  swoole_process::kill($pid, 0)這句話是指的 $signo=0,可以檢測進程是否存在,不會發送信號(swoole文檔里面有說明,附傳送門:https://wiki.swoole.com/wiki/page/219.html)

  發送SIGUSR1命令 ,但是我再后面的測試過程中發現,這個指令並沒有什么用,不即時

static public function params_r($opt)
    {
        if (isset($opt["r"]) || isset($opt["reload"])) {
            $pid = @file_get_contents(Crontab::$pid_file);
            if ($pid) {
                if (swoole_process::kill($pid, 0)) {
                    swoole_process::kill($pid, SIGUSR1);
                    Main::log_write("對 {$pid} 發送了從新載入配置文件的信號");
                    exit;
                }
            }
            Main::log_write("進程" . $pid . "不存在");
        }
    }  

行52:self::params_worker($opt);Crontab::$worker = true;具體功能:設置開啟工作進程,解釋是:工廠要生成很多商品,將不同的商品流水線交給不同的工人進行生產處理

行53:self::params_tasktype($opt);//task任務獲取類型,[file|mysql] 默認是file 這里其實看源碼最起碼從main.php是看不到此類限制,但是在include/loadtask/LoadTasks.class.php里面的構造方法里面有這種判斷

行54:self::params_checktime($opt);//Crontab::$checktime = false; 

行55:$opt = self::params_m($opt);//源碼里面很清楚,檢測進程是否存在,如果存在則重新設置參數數組,標示重啟執行-s restart

行56:self::params_s($opt);//這里是核心方法,下節開始分析

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM