Subversion Repositories php-qbpwcf

Rev

Rev 3 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#!/usr/bin/php
<?php

/*
        QBPWCF, Quick Build PHP website Component base on Fedora Linux.
    Copyright (C) 2014~2025 MIN ZHI, CHEN

    This file is part of QBPWCF.

    QBPWCF is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    QBPWCF is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with QBPWCF.  If not, see <http://www.gnu.org/licenses/>.

*/

/*

說明:
監控系統若負載超過總執行序就警報

參考資料:
https://www.php.net/manual/en/function.htmlentities.php

*/

#使用命名空間qbpwcf
namespace qbpwcf;

#取得 lib path
exec("php -f ".escapeshellarg(pathinfo(__FILE__)["dirname"]."/libexec/folderOfUsrLib.php"),$output,$status);

#如果執行失敗
if($status!==0){

        #debug
        var_dump(__LINE__,$output);

        #結束執行,回傳shell 1.
        exit(1);

        }#if end

#儲存lib path
$folderOfUsrLib=$output[0];

#以該檔案的實際位置的 lib path 為 include path 首位
$output=array();
exec("cd ".escapeshellarg(pathinfo(__FILE__)["dirname"]."/../".$folderOfUsrLib."/qbpwcf").";pwd;",$output,$status);

#如果執行失敗
if($status!==0){

        #debug
        var_dump(__LINE__,$output);

        #結束執行,回傳shell 1.
        exit(1);

        }#if end

#設置 include path
set_include_path($output[0].PATH_SEPARATOR.get_include_path());

#匯入外部套件
include("allInOne.php");

#上一封信件寄送的分鐘
$lastEmailMinute=gmdate("i");

#預設執行間隔為1秒鐘
$interval=1;

#預設不開啟所有訊息
$verbose=false;

#預設每天執行的時間範圍為0跟23,亦即每個小時都執行
$s=0;
$e=23;

#函式說明:
#抓取命令列的參數.
#回傳結果:
#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
#$reuslt["error"],執行不正常結束的錯訊息陣列.
#$result["function"],當前執行的函式名稱.
#$result["argu"],使用的參數陣列.
#$result["content"],要回傳的參數陣列.
#$result["count"],參數的數量.
#必填參數:
#無
#可省略參數:
#$conf["echo"],"true"代表要將抓到的參數一個個印出來,"false"代表用回傳的方式,預設為"false".
$conf["echo"]="false";
$getArgu=cmd::getArgu($conf);
unset($conf);

#如果執行失敗
if($getArgu["status"]==="false"){

        #結束執行
        return false;

        }#if end

#如果存在一個參數
if(isset($getArgu["content"][1])){

        #如果有參數 -h 或 --help 存在
        if( $getArgu["content"][1]==="-h" || $getArgu["content"][1]==="--help" ){

                #印出指令說明
                echo "Usage ".basename(__FILE__).":".PHP_EOL;
                echo "\t-i 秒數間隔 -s 開始小時 -e 結束小時".PHP_EOL;
                echo "\t--verbose on 代表提示所有訊息".PHP_EOL;
                echo "\t--eacct 用於寄信的gmail賬戶".PHP_EOL;
                echo "\t--epass 用於寄信的gmail密碼".PHP_EOL;
                echo "\t--receiver 收件人,一次指定一個收件人".PHP_EOL;
                echo "\t--target 監控的主機名稱".PHP_EOL;

                #結束執行
                exit;

                }#if end

        }#if end

#函式說明:
#解析參數.
#回傳結果:
#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
#$reuslt["error"],執行不正常結束的錯訊息陣列.
#$result["function"],當前執行的函式名稱.
#$result["content"],解析好的參數陣列.
#$result["content"][$key][$i],參數 $key 的 $i+1 個參數數值內容.
#$result["program"],字串,執行的程式名稱.
#必填參數:
#無
#可省略參數:
#無
#備註:
#僅能在命令列底下執行.
#建議:
#以後可將參數 --a--b 的名稱與後面的數值 $value 存成 $result["a"]["b"][$i]=$value .
$conf=array();
$parseArgu=cmd::parseArgu($conf);
unset($conf);

#如果執行失敗
if($parseArgu["status"]==="false"){

        #結束執行
        return false;

        }#if end

#如果有參數
if(isset($parseArgu["content"])){

        #如果有參數 i
        if(isset($parseArgu["content"]["i"])){

                #如果有一個參數 i
                if(isset($parseArgu["content"]["i"][0])){

                        #如果是正常的數值
                        if((int)$parseArgu["content"]["i"][0]>0){

                                #設置新的 interval
                                $interval=(int)$parseArgu["content"]["i"][0];

                                }#if end

                        }#if end

                }#if end

        #如果有參數 s
        if(isset($parseArgu["content"]["s"])){

                #如果有一個參數 s
                if(isset($parseArgu["content"]["s"][0])){

                        #如果是正常的數值
                        if( (int)$parseArgu["content"]["s"][0]>0 && (int)$parseArgu["content"]["s"][0]<23 ){

                                #設置新的開始小時
                                $s=(int)$parseArgu["content"]["s"][0];

                                }#if end

                        }#if end

                }#if end

        #如果有參數 e
        if(isset($parseArgu["content"]["e"])){

                #如果有一個參數 e
                if(isset($parseArgu["content"]["e"][0])){

                        #如果是正常的數值
                        if( (int)$parseArgu["content"]["e"][0]>0 && (int)$parseArgu["content"]["e"][0]<23 ){

                                #設置新的結束小時
                                $e=(int)$parseArgu["content"]["e"][0];

                                }#if end

                        }#if end

                }#if end

        #如果有參數 verbose
        if(isset($parseArgu["content"]["verbose"])){

                #如果有一個參數verbose
                if(isset($parseArgu["content"]["verbose"][0])){

                        #設置要 verbose
                        $verbose=true;

                        }#if end

                }#if end

        #如果有參數 eacct
        if(isset($parseArgu["content"]["eacct"])){

                #如果有一個參數eacct
                if(isset($parseArgu["content"]["eacct"][0])){

                        #設置eacct
                        $eacct=$parseArgu["content"]["eacct"][0];

                        }#if end

                }#if end

        #如果有參數 epass
        if(isset($parseArgu["content"]["epass"])){

                #如果有一個參數epass
                if(isset($parseArgu["content"]["epass"][0])){

                        #設置epass
                        $epass=$parseArgu["content"]["epass"][0];

                        }#if end

                }#if end

        #如果有參數 receiver
        if(isset($parseArgu["content"]["receiver"])){

                #設置receiver
                $receiver=$parseArgu["content"]["receiver"];

                }#if end

        #如果有參數 target
        if(isset($parseArgu["content"]["target"])){

                #如果有一個參數target
                if(isset($parseArgu["content"]["target"][0])){

                        #設置target
                        $target=$parseArgu["content"]["target"][0];

                        }#if end

                }#if end

        }#if end

#如果參數有缺
if( !isset($eacct) || !isset($epass) || !isset($receiver) || !isset($target) )
{
        echo "參數 --eacct 跟 --epass 跟 --receiver 跟 --target 必填".PHP_EOL;
        exit;
}

#預設上次不需要警示
$lastAlert=false;

#預設上次的警示數值為0
$lastAlertValue=0;

#無窮迴圈
while(true){

        #取得現在時間
        #涵式說明:
        #呼叫shell執行系統命令,並取得回傳的內容.
        #回傳的結果:
        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$result["function"],當前執行的函數名稱.
        #$result["argu"],使用的參數.
        #$result["cmd"],執行的指令內容.
        #$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.
        #$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.
        #$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.
        #$result["running"],是否還在執行.
        #$result["pid"],pid.
        #$result["statusCode"],執行結束後的代碼.
        #必填的參數
        #$conf["command"],字串,要執行的指令與.
        $conf["command"]="date";
        #$conf["fileArgu"],字串,變數__FILE__的內容.
        $conf["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
        $conf["argu"]=array("-d","now","+%H");
        #$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").
        #$conf["arguIsAddr"]=array();
        #$conf["pre"],陣列,要在本指令前執行的每個指令與參數.
        #$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.
        #$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.
        #$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".
        #$conf["enablePrintDescription"]="true";
        #$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.
        #$conf["printDescription"]="";
        #$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".
        $conf["escapeshellarg"]="true";
        #$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.
        #$conf["username"]="";
        #$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.
        #$conf["password"]="";
        #$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".
        #$conf["useScript"]="";
        #$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".
        #$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";
        #$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.
        #$conf["inBackGround"]="";
        #$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.
        #$conf["getErr"]="false";
        #備註:
        #不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.
        #參考資料:
        #exec=>http://php.net/manual/en/function.exec.php
        #escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php
        #escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php
        $callShell=external::callShell($conf);
        unset($conf);

        #如果執行出錯
        if($callShell["status"]===false){

                #結束執行
                return false;

                }#if end

        #如果沒有回小時
        if(!isset($callShell["output"][0])){

                #結束執行
                return false;

                }#if end

        #取得輸出
        $hour=$callShell["output"][0];

        #如果小於開始小時
        if($hour<(int)$s){

                #休息一小時
                sleep(3600);

                #再跑一次
                continue;

                }#if end

        #如果大於結束小時
        if($hour>(int)$e){

                #休息一小時
                sleep(3600);

                #再跑一次
                continue;

                }#if end

        #取得現在時間
        #涵式說明:
        #呼叫shell執行系統命令,並取得回傳的內容.
        #回傳的結果:
        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$result["function"],當前執行的函數名稱.
        #$result["argu"],使用的參數.
        #$result["cmd"],執行的指令內容.
        #$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.
        #$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.
        #$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.
        #$result["running"],是否還在執行.
        #$result["pid"],pid.
        #$result["statusCode"],執行結束後的代碼.
        #必填的參數
        #$conf["command"],字串,要執行的指令與.
        $conf["command"]="date";
        #$conf["fileArgu"],字串,變數__FILE__的內容.
        $conf["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
        #$conf["argu"]=array("");
        #$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").
        #$conf["arguIsAddr"]=array();
        #$conf["pre"],陣列,要在本指令前執行的每個指令與參數.
        #$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.
        #$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.
        #$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".
        #$conf["enablePrintDescription"]="true";
        #$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.
        #$conf["printDescription"]="";
        #$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".
        $conf["escapeshellarg"]="true";
        #$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.
        #$conf["username"]="";
        #$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.
        #$conf["password"]="";
        #$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".
        #$conf["useScript"]="";
        #$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".
        #$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";
        #$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.
        #$conf["inBackGround"]="";
        #$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.
        #$conf["getErr"]="false";
        #備註:
        #不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.
        #參考資料:
        #exec=>http://php.net/manual/en/function.exec.php
        #escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php
        #escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php
        $callShell=external::callShell($conf);
        unset($conf);

        #如果執行出錯
        if($callShell["status"]==="false"){

                #結束執行
                return false;

                }#if end

        #取得輸出
        $time=$callShell["output"];

        #涵式說明:
        #呼叫shell執行系統命令,並取得回傳的內容.
        #回傳的結果:
        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$result["function"],當前執行的函數名稱.
        #$result["argu"],使用的參數.
        #$result["cmd"],執行的指令內容.
        #$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.
        #$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.
        #$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.
        #$result["running"],是否還在執行.
        #$result["pid"],pid.
        #$result["statusCode"],執行結束後的代碼.
        #必填的參數
        #$conf["command"],字串,要執行的指令與.
        $conf["command"]="uptime";
        #$conf["fileArgu"],字串,變數__FILE__的內容.
        $conf["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
        #$conf["argu"]=array("");
        #$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").
        #$conf["arguIsAddr"]=array();
        #$conf["pre"],陣列,要在本指令前執行的每個指令與參數.
        #$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.
        #$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.
        #$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".
        #$conf["enablePrintDescription"]="true";
        #$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.
        #$conf["printDescription"]="";
        #$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".
        $conf["escapeshellarg"]="true";
        #$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.
        #$conf["username"]="";
        #$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.
        #$conf["password"]="";
        #$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".
        #$conf["useScript"]="";
        #$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".
        #$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";
        #$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.
        #$conf["inBackGround"]="";
        #$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.
        #$conf["getErr"]="false";
        #備註:
        #不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.
        #參考資料:
        #exec=>http://php.net/manual/en/function.exec.php
        #escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php
        #escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php
        $callShell=external::callShell($conf);
        unset($conf);

        #如果執行出錯
        if($callShell["status"]===false){

                #結束執行
                return false;

                }#if end

        #取得輸出
        $uptime=$callShell["output"];

        #用來分割的關鍵字
        $splitWord="load average: ";

        #函式說明:
        #將固定格式的字串分開,並回傳分開的結果。
        #回傳結果:
        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列
        #$result["function"],當前執行的函數名稱.
        #$result["argu"],使用的參數.
        #$result["oriStr"],要分割的原始字串內容
        #$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
        #$result["dataCounts"],爲總共分成幾段
        #$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
        #必填參數:
        #$conf["stringIn"],字串,要處理的字串.
        $conf["stringIn"]=$uptime[0];
        #$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
        $conf["spiltSymbol"]=$splitWord;
        #可省略參數:
        #$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
        $conf["allowEmptyStr"]="false";
        #備註:
        #無.
        $spiltString=stringProcess::spiltString($conf);
        unset($conf);

        #如果執行失敗
        if($spiltString["status"]==="false")
        {
                #結束執行
                return false;
        }

        #如果沒有指令的關鍵字存在
        if($spiltString["found"]==="false")
        {
                #結束執行
                return false;
        }

        #用來分割的關鍵字
        $splitWord=", ";

        #函式說明:
        #將固定格式的字串分開,並回傳分開的結果。
        #回傳結果:
        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列
        #$result["function"],當前執行的函數名稱.
        #$result["argu"],使用的參數.
        #$result["oriStr"],要分割的原始字串內容
        #$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
        #$result["dataCounts"],爲總共分成幾段
        #$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
        #必填參數:
        #$conf["stringIn"],字串,要處理的字串.
        $conf["stringIn"]=$spiltString["dataArray"][1];
        #$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
        $conf["spiltSymbol"]=$splitWord;
        #可省略參數:
        #$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
        $conf["allowEmptyStr"]="false";
        #備註:
        #無.
        $spiltString=stringProcess::spiltString($conf);
        unset($conf);

        #如果執行失敗
        if($spiltString["status"]==="false")
        {
                #結束執行
                return false;
        }

        #如果沒有指令的關鍵字存在
        if($spiltString["found"]==="false")
        {
                #結束執行
                return false;
        }

        #取得uptime的當下數值
        $uptimeVal=$spiltString["dataArray"][0];

        #取得CPU有多少執行序
        #涵式說明:
        #呼叫shell執行系統命令,並取得回傳的內容.
        #回傳的結果:
        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$result["function"],當前執行的函數名稱.
        #$result["argu"],使用的參數.
        #$result["cmd"],執行的指令內容.
        #$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.
        #$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.
        #$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.
        #$result["running"],是否還在執行.
        #$result["pid"],pid.
        #$result["statusCode"],執行結束後的代碼.
        #必填的參數
        #$conf["command"],字串,要執行的指令與.
        $conf["command"]="lscpu";
        #$conf["fileArgu"],字串,變數__FILE__的內容.
        $conf["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
        $conf["argu"]=array("|","grep","CPU(s)","|","grep","-v","NUMA");
        #$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").
        #$conf["arguIsAddr"]=array();
        #$conf["pre"],陣列,要在本指令前執行的每個指令與參數.
        #$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.
        #$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.
        #$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".
        #$conf["enablePrintDescription"]="true";
        #$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.
        #$conf["printDescription"]="";
        #$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".
        $conf["escapeshellarg"]="true";
        #$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.
        #$conf["username"]="";
        #$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.
        #$conf["password"]="";
        #$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".
        #$conf["useScript"]="";
        #$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".
        #$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";
        #$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.
        #$conf["inBackGround"]="";
        #$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.
        #$conf["getErr"]="false";
        #備註:
        #不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.
        #參考資料:
        #exec=>http://php.net/manual/en/function.exec.php
        #escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php
        #escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php
        $callShell=external::callShell($conf);
        unset($conf);

        #如果執行出錯
        if($callShell["status"]==="false"){

                #結束執行
                return false;

                }#if end

        #取得輸出
        $lscpu=$callShell["output"];

        #用來分割的關鍵字
        $splitWord="CPU(s): ";

        #函式說明:
        #將固定格式的字串分開,並回傳分開的結果。
        #回傳結果:
        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列
        #$result["function"],當前執行的函數名稱.
        #$result["argu"],使用的參數.
        #$result["oriStr"],要分割的原始字串內容
        #$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
        #$result["dataCounts"],爲總共分成幾段
        #$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
        #必填參數:
        #$conf["stringIn"],字串,要處理的字串.
        $conf["stringIn"]=$lscpu[0];
        #$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
        $conf["spiltSymbol"]=$splitWord;
        #可省略參數:
        #$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
        $conf["allowEmptyStr"]="false";
        #備註:
        #無.
        $spiltString=stringProcess::spiltString($conf);
        unset($conf);

        #如果執行失敗
        if($spiltString["status"]==="false")
        {
                #結束執行
                return false;
        }

        #如果沒有指令的關鍵字存在
        if($spiltString["found"]==="false")
        {
                #結束執行
                return false;
        }

        #取得uptime的當下數值
        $lscpuVal=(int)$spiltString["dataArray"][0];

        #如果有程序必須等待cpu給予資源
        if($uptimeVal>=$lscpuVal)
        {
                #設置需要警示
                $alert=true;
        }
        #反之解除
        else
        {
                #設置需要警示
                $alert=false;
        }

        #設置警示數值
        $alertValue=$uptimeVal;

        #取得當前程序樹
        #涵式說明:
        #呼叫shell執行系統命令,並取得回傳的內容.
        #回傳的結果:
        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$result["function"],當前執行的函數名稱.
        #$result["argu"],使用的參數.
        #$result["cmd"],執行的指令內容.
        #$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.
        #$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.
        #$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.
        #$result["running"],是否還在執行.
        #$result["pid"],pid.
        #$result["statusCode"],執行結束後的代碼.
        #必填的參數
        #$conf["command"],字串,要執行的指令與.
        $conf["command"]="ps";
        #$conf["fileArgu"],字串,變數__FILE__的內容.
        $conf["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
        $conf["argu"]=array("axuwf","|","cat");
        #$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").
        #$conf["arguIsAddr"]=array();
        #$conf["pre"],陣列,要在本指令前執行的每個指令與參數.
        #$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.
        #$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.
        #$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".
        #$conf["enablePrintDescription"]="true";
        #$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.
        #$conf["printDescription"]="";
        #$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".
        $conf["escapeshellarg"]="true";
        #$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.
        #$conf["username"]="";
        #$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.
        #$conf["password"]="";
        #$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".
        #$conf["useScript"]="";
        #$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".
        #$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";
        #$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.
        #$conf["inBackGround"]="";
        #$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.
        #$conf["getErr"]="false";
        #備註:
        #不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.
        #參考資料:
        #exec=>http://php.net/manual/en/function.exec.php
        #escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php
        #escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php
        $callShell=external::callShell($conf);
        unset($conf);

        #如果執行出錯
        if($callShell["status"]==="false"){

                #結束執行
                return false;

                }#if end

        #取得輸出
        $output=$callShell["output"];

        #$time,現在時間
        #$uptime,load average.
        #$output,完整工作程序樹

        #設置郵件參數
        $conf["acct"]=$eacct;
        $conf["pass"]=$epass;
        $conf["receiver"]=$receiver;

        #設置時間
        $date=date("Y-m-d H:i:s");

        #如果從正常狀態進入需要警示的狀態
        if($lastAlert===false && $alert===true)
        {
                #警示超過負荷
                $conf["subject"]=$conf["plainBody"]=$conf["htmlBody"]=$target." 於 ".$date." 超過負荷(".$alertValue.">".$lscpuVal.")了".PHP_EOL;

                #串接完整的工作樹
                foreach($output as $line)
                {
                        $conf["plainBody"]=$conf["plainBody"].PHP_EOL.$line;
                        $conf["htmlBody"]=$conf["htmlBody"]."<br>".htmlentities($line);
                }

                #寄送通知信件
                sendMail($conf);

                #更新寄送的分鐘
                $lastEmailMinute=gmdate("i");

        }#if end

        #反之如果負載更嚴重了
        else if($lastAlert===true && $alert===true && $alertValue>$lastAlertValue)
        {
                #警示超過負荷
                $conf["subject"]=$conf["plainBody"]=$conf["htmlBody"]=$target." 於 ".$date." 負荷更重了(".$alertValue.">".$lscpuVal.")了".PHP_EOL;

                #如果不同分鐘,且超過5分鐘了
                if($lastEmailMinute!==gmdate("i") && (gmdate("i")-$lastEmailMinute)>5 )
                {
                        #串接完整的工作樹
                        foreach($output as $line)
                        {
                                $conf["plainBody"]=$conf["plainBody"].PHP_EOL.$line;
                                $conf["htmlBody"]=$conf["htmlBody"]."<br>".htmlentities($line);
                        }

                        #加上pre tag
                        $conf["htmlBody"]="<pre>".$conf["htmlBody"]."<pre/>";

                        #寄送通知信件
                        sendMail($conf);

                        #更新寄送的分鐘
                        $lastEmailMinute=gmdate("i");

                }#if end

        }#if end

        #反之如果可以負荷了
        else if($lastAlert===true && $alert===false)
        {
                #提示恢復正常了
                $conf["subject"]=$conf["plainBody"]=$conf["htmlBody"]=$target." 於 ".$date." 恢復正常了".PHP_EOL;

                #串接完整的工作樹
                foreach($output as $line)
                {
                        $conf["plainBody"]=$conf["plainBody"].PHP_EOL.$line;
                        $conf["htmlBody"]=$conf["htmlBody"]."<br>".htmlentities($line);
                }

                #加上pre tag
                $conf["htmlBody"]="<pre>".$conf["htmlBody"]."<pre/>";

                #寄送通知信件
                sendMail($conf);

        }#if end

        #其他不需要警示與提示的狀況,如果有開啟 $verbose
        else if($verbose===true)
        {
                #verbose訊息
                $conf["subject"]=$conf["plainBody"]=$conf["htmlBody"]=$target." 於 ".$date." 正常(".$alertValue."<".$lscpuVal.")".PHP_EOL;

                #如果不同分鐘,且超過5分鐘了
                if($lastEmailMinute!==gmdate("i") && (gmdate("i")-$lastEmailMinute)>5 )
                {
                        #串接完整的工作樹
                        foreach($output as $line)
                        {
                                $conf["plainBody"]=$conf["plainBody"].PHP_EOL.$line;
                                $conf["htmlBody"]=$conf["htmlBody"]."<br>".htmlentities($line);
                        }

                        #加上pre tag
                        $conf["htmlBody"]="<pre>".$conf["htmlBody"]."<pre/>";

                        #寄送通知信件
                        sendMail($conf);

                        #更新寄送的分鐘
                        $lastEmailMinute=gmdate("i");

                }#if end

        }#else end

        #移除mail參數
        unset($conf);

        #更新上次的是否需要警示識別
        $lastAlert=$alert;

        #更新上次的警示數值為
        $lastAlertValue=$alertValue;

        #休息 $interval 秒
        sleep($interval);

        }#while end

#寄送email
function sendMail($conf)
{
        #接收參數
        $acct=$conf["acct"];
        $pass=$conf["pass"];
        $receiver=$conf["receiver"];
        $subject=$conf["subject"];
        $plainBody=$conf["plainBody"];
        $htmlBody=$conf["htmlBody"];
        unset($conf);

        #函式說明:
        #使用 curl 來透過SMTP伺服器寄信
        #回傳結果:
        #$result["status"],寄信的情況,若爲"true",則十之八九沒有問題.
        #$result["error"],錯誤訊息陣列
        #$result["function"],當前執行的函數
        #$result["warning"],警示訊息,一些不會導致失敗但不能說是完美的問題.
        #$result["cmd"],寄信的指令.
        #$result["detailCmd"],較詳細的寄信指令.
        #必填參數:
        #$conf["username"],字串,用來登入郵件伺服器的帳號
        $conf["username"]=$acct;
        #$conf["password"],字串,用來登入郵件伺服器的密碼
        $conf["password"]=$pass;
        #$conf["receiverMail"],陣列,收件人的信箱
        $conf["receiverMail"]=$receiver;
        #$conf["subject"],字串,郵件的主題
        $conf["subject"]=$subject;
        #$conf["plainBody"],字串,郵件本文的純文字內容.
        $conf["plainBody"]=$plainBody;
        #$conf["htmlBody"]="";,字串,郵件本文的html內容,多媒體盡量不要用base64的方式來嵌入,因為大部分的郵件服務(Gmail)都不支援,如果是在單機上的郵件軟體就可能有支援,例如:Evolution.
        $conf["htmlBody"]=$htmlBody;
        #$conf["fileArgu"],字串,php內建變數「__FILE__」的內容.
        $conf["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["mailServer"],字串,要使用的SMTP郵件伺服器網址與連接口,預設爲 smtps://smtp.gmail.com:465
        #$conf["mailServer"]="";
        #$conf["mailerMailDisplay"],字串,要顯示的寄件人信箱,預設爲 $conf["username"]
        #$conf["mailerMailDisplay"]="";
        #$conf["mailerNameDisplay"],字串,要顯示的寄件人姓名,預設爲 $conf["username"]
        #$conf["mailerNameDisplay"]="";
        #$conf["receiverMailDisplay"],陣列,要顯示的收件人信箱,預設爲 $conf["receiverMail"] 對應的元素.
        #$conf["receiverMailDisplay"]="";#
        #$conf["receiverNameDisplay"],陣列,要顯示的收件人姓名,預設爲 $conf["receiverMail"] 對應的元素.
        #$conf["receiverNameDisplay"]="";
        #$conf["attachment"],陣列,每個要寄送的附件路徑與檔案名稱
        #$conf["attachment"]=array();
        #$conf["attachmentName"],陣列,每個要寄送的附件顯示名稱,預設為$conf["attachment"]中的實際檔案名稱.
        #$conf["attachmentName"]=array();
        #$conf["attachmentMimeType"],陣列,每個附件的 mimeType,預設為"application/*".
        #$conf["attachmentMimeType"]array();
        #範例語句:
        #curl --url smtps://smtp.gmail.com:465 -u username@gmail.com:userPassword --mail-from username@gmail.com --mail-rcpt receiver@mail.com --upload-file mail.txt -v
        #範例信件內容:
        #From: "userName" <username@gmail.com>
        #To: "receiverName" <userPassword@yahoo.com.tw>
        #Subject: This is a test
        #本文~
        #參考資料來源:
        #用curl來寄信=>http://stackoverflow.com/questions/14722556/using-curl-to-send-email
        #降低安全性標準讓curl可以使用=>https://www.google.com/settings/security/lesssecureapps
        #信件內容header的設定=>http://jjdai.zhupiter.com/2010/10/php-%E5%A6%82%E4%BD%95%E5%82%B3%E9%80%81%E4%B8%80%E5%B0%81-mime-html-%E6%A0%BC%E5%BC%8F%E7%9A%84-email-%E4%BF%A1%E4%BB%B6/
        #檔案每列不得超超過70個字元=>http://php.net/manual/en/function.mail.php
        #寄信給多人=>https://github.com/curl/curl/issues/784
        #備註:
        #信件的內容格式有錯,導致本文無法顯示.
        $curlSmtp=mail::curlSmtp($conf);
        unset($conf);

        #如果執行失敗
        if($curlSmtp["status"]==="false")
        {
                #印出內容
                var_dump($curlSmtp);

                #結束執行
                exit;

        }#if end

}#function sendMail end