Rev 466 | Rev 883 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#!/bin/php<?php/*QBPWCF, Quick Build PHP website Component base on Fedora Linux.Copyright (C) 2015~2024 Min-Jhin,ChenThis file is part of QBPWCF.QBPWCF is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with QBPWCF. If not, see <http://www.gnu.org/licenses/>.*//*說明:監控系統若負載超過總執行序就警報參考資料:https://www.php.net/manual/en/function.htmlentities.php*/#使用命名空間qbpwcfnamespace qbpwcf;#以該檔案的實際位置的 lib path 為 include path 首位exec("cd ".pathinfo(__FILE__)["dirname"]."/../../;pwd;",$output,$status);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"])){#如果有參數 iif(isset($parseArgu["content"]["i"])){#如果有一個參數 iif(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#如果有參數 sif(isset($parseArgu["content"]["s"])){#如果有一個參數 sif(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#如果有參數 eif(isset($parseArgu["content"]["e"])){#如果有一個參數 eif(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#如果有參數 verboseif(isset($parseArgu["content"]["verbose"])){#如果有一個參數verboseif(isset($parseArgu["content"]["verbose"][0])){#設置要 verbose$verbose=true;}#if end}#if end#如果有參數 eacctif(isset($parseArgu["content"]["eacct"])){#如果有一個參數eacctif(isset($parseArgu["content"]["eacct"][0])){#設置eacct$eacct=$parseArgu["content"]["eacct"][0];}#if end}#if end#如果有參數 epassif(isset($parseArgu["content"]["epass"])){#如果有一個參數epassif(isset($parseArgu["content"]["epass"][0])){#設置epass$epass=$parseArgu["content"]["epass"][0];}#if end}#if end#如果有參數 receiverif(isset($parseArgu["content"]["receiver"])){#設置receiver$receiver=$parseArgu["content"]["receiver"];}#if end#如果有參數 targetif(isset($parseArgu["content"]["target"])){#如果有一個參數targetif(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#其他不需要警示與提示的狀況,如果有開啟 $verboseelse 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#寄送emailfunction 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