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/>.

*/

/*
說明:
用來檢測本機跟1.1.1.1、8.8.8.8是否連線正常,若不正常則用email提示或輸出訊息就好.檢查頻率為60秒一次.
*/

#使用命名空間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");

#說明用法的函式
function help(){

        #函式說明:
        #印出多行文字,結尾自動換行.
        #回傳的結果:
        #$result["status"],執行是否成功,"true"代表成功,"false"代表失敗.
        #$result["function"],當前執行的函數名稱.
        #$result["error"],錯誤訊息陣列.
        #必填的參數:
        #$conf["outputStringArray"],字串陣列,每行要印出的文字內容.
        $conf["outputStringArray"][]=$_SERVER["argv"][0]." 用法:";
        $conf["outputStringArray"][]="--addPingTarget pingTarget #新增 pingTarget 為要增加檢測是否可以連線的目標.";
        $conf["outputStringArray"][]="--emailAcct email account #設置寄信用的帳號,若無設置則為用本機直接寄送.";
        $conf["outputStringArray"][]="--emailPass email password #設置寄信用帳號的密碼.";
        $conf["outputStringArray"][]="--receiver email #收件人的信箱,若有多個收件人請重複使用該參數.若無該參數則不會寄信只會印出訊息";
        $conf["outputStringArray"][]="--levelForCheckSSL force/losse/none #ssl憑證的規範,\"force\"代表一定要符合;\"loose\"代表第2次嘗試可以不符合;\"none\"代表不用符合";
        $echoMultiLine=cmd::echoMultiLine($conf);
        unset($conf);

        #如果解析內容失敗
        if($echoMultiLine["status"]==="false"){

                #印出結果
                var_dump($echoMultiLine);

                #結束程式
                exit;

                }#if end

        #結束執行
        exit;

        }#function end

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

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

        #debug
        var_dump($parseArgu);

        #結束執行
        exit;

        }#if end

#初始化ping的目標為 1.1.1.1 跟 8.8.8.8
$pingTarget=array("1.1.1.1","8.8.8.8");

#如果有新增ping的目標
if(isset($parseArgu["content"]["addPingTarget"])){

        #針對每個要增加ping的對象
        foreach($parseArgu["content"]["addPingTarget"] as $newPingTarget){

                #增加新的ping目標
                $pingTarget[]=$newPingTarget;

                }#foreach end

        }#if end

#如果沒有設置收件人
if(!isset($parseArgu["content"]["receiver"])){

        #設置不寄信只輸出訊息就好
        $echoOnly="true";

        }#if end

#反之
else{

        #不要只輸出訊息
        $echoOnly="false";

        #取得收件人
        $receiver=$parseArgu["content"]["receiver"];

        }#else end

#如果沒有設置寄信用的 email 跟 密碼
if( !isset($parseArgu["content"]["emailAcct"]) || !isset($parseArgu["content"]["emailPass"]) ){

        #設置不要用smtp來寄信
        $sendBySmtp="false";

        }#if end

#反之
else{

        #設置要用smtp寄信
        $sendBySmtp="true";

        }#else end

#預設為寬鬆的設定
$levelForCheckSSL="loose";

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

        #如果確實有該參數
        if(isset($parseArgu["content"]["levelForCheckSSL"][0])){

                #取得其設定
                $levelForCheckSSL=$parseArgu["content"]["levelForCheckSSL"][0];

                }#if end

        }#if end

#無窮迴圈
while(true){

        #初始化不用警報
        $needAlarm="false";

        #針對每個 ping target
        foreach($pingTarget as $pt){

                #函式說明:
                #呼叫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"]="ping";
                #$conf["fileArgu"],字串,變數__FILE__的內容.
                $conf["fileArgu"]=__FILE__;
                #可省略參數:
                #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
                $conf["argu"]=array("-q","-W","1","-c","1",$pt);
                #$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);

                #如果執行失敗,且不是狀態1或狀態2
                if($callShell["status"]==="false" && $callShell["statusCode"]!==1 && $callShell["statusCode"]!==2){

                        #debug
                        var_dump($callShell);

                        #結束執行
                        exit;

                        }#if end

                #針對每行輸出
                /*
                PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.

                --- 1.1.1.1 ping statistics ---
                1 packets transmitted, 1 received, 0% packet loss, time 0ms
                rtt min/avg/max/mdev = 46.251/46.251/46.251/0.000 ms
                */

                #函式說明:
                #檢查多個字串中的每個字串是否有多個關鍵字
                #回傳結果:
                #$result["status"],整體來說,執行是否成功,"true"代表執行成功,"false"代表執行失敗。
                #$result["function"],當前執行的函數名稱.
                #$result["error"],錯誤訊息.
                #$result["argu"],使用的參數.
                #$result["foundedTrueKey"],結果為"true"的被搜尋元素key陣列.
                #$result["foundedKeyWords"],找到的關鍵字.
                #$result["foundedFalseKey"],結果為"false"的被搜尋元素key陣列.
                #$result["foundedTrueKeyWords"],二維陣列,各個字串有找到的關鍵字陣列.
                #$result["foundedAll"],是否每個關鍵字都有找到,"true"代表每個都有找到,"false"代表沒有每個都找到.
                #必填參數:
                $conf["keyWords"]=array("0% packet loss");#想要搜尋的關鍵字
                $conf["stringArray"]=$callShell["output"];#要被搜尋的字串內容陣列
                #可省略參數:
                #$conf["completeEqual"]="true";#是否內容要完全符合,不能多出任何不符合的內容,預設為"false"不需要完全符合.
                #備註:
                #無.
                $findManyKeyWordsFromManyString=search::findManyKeyWordsFromManyString($conf);
                unset($conf);

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

                        #debug
                        var_dump($findManyKeyWordsFromManyString);

                        #結束執行
                        exit;

                        }#if end

                #若沒有無遺失封包
                if($findManyKeyWordsFromManyString["foundedAll"]==="false"){

                        #設置需要警報
                        $needAlarm="true";

                        #跳出foreach
                        break;

                        }#if end

                }#foreach end

        #如果需要警報
        if($needAlarm==="true"){

                #如果只要印出訊息
                if($echoOnly==="true"){

                        #提示
                        echo "目前無法連線到指定的伺服器,請確認網路環境!".PHP_EOL;

                        #休息60秒
                        sleep(60);

                        #繼續執行
                        continue;

                        }#if end

                #如果不透過smtp來寄信
                if($sendBySmtp==="false"){

                        #函式說明:
                        #透過php的mail函數寄信
                        #回傳結果:
                        #$result["status"],寄信的情況,若爲"true",則十之八九沒有問題.
                        #$result["error"],錯誤訊息陣列
                        #$result["function"],當前執行的函數
                        #必填參數:
                        #$conf["to"],字串陣列,收件人們的信箱.
                        $conf["to"]=$receiver;
                        #$conf["subject"],字串,郵件標題.
                        $conf["subject"]="目前無法連線到指定的伺服器,請確認網路環境!";
                        #$conf["content"],字串,要寄送的訊息內容.
                        $conf["content"]="目前無法連線到指定的伺服器,請確認網路環境!";
                        #可省略參數:
                        #$conf["mailerEmail"],字串,顯示的寄件人.
                        #$conf["mailerEmail"]="";
                        #參考資料:
                        #mail=>https://www.php.net/manual/en/function.mail.php
                        #Internet Message Format=>http://www.faqs.org/rfcs/rfc2822
                        $sendMail=mail::sendMail($conf);
                        unset($conf);

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

                                #debug
                                var_dump($sendMail);

                                #結束執行
                                exit;

                                }#if end

                        #休息60秒
                        sleep(60);

                        #繼續執行
                        continue;

                        }#if end

                #到這邊代表要用smtp寄信
                #函式說明:
                #使用 curl 來透過SMTP伺服器寄信
                #回傳結果:
                #$result["status"],寄信的情況,若爲"true",則十之八九沒有問題.
                #$result["error"],錯誤訊息陣列
                #$result["function"],當前執行的函數
                #$result["warning"],警示訊息,一些不會導致失敗但不能說是完美的問題.
                #$result["cmd"],寄信的指令.
                #$result["detailCmd"],較詳細的寄信指令.
                #必填參數:
                #$conf["username"],字串,用來登入郵件伺服器的帳號
                $conf["username"]=$parseArgu["content"]["emailAcct"];
                #$conf["password"],字串,用來登入郵件伺服器的密碼
                $conf["password"]=$parseArgu["content"]["emailPass"];
                #$conf["receiverMail"],陣列,收件人的信箱
                $conf["receiverMail"]=$parseArgu["content"]["receiver"];
                #$conf["subject"],字串,郵件的主題
                $conf["subject"]="目前無法連線到指定的伺服器,請確認網路環境!";
                #$conf["plainBody"],字串,郵件本文的純文字內容.
                $conf["plainBody"]="目前無法連線到指定的伺服器,請確認網路環境!";
                #$conf["htmlBody"]="";,字串,郵件本文的html內容,多媒體盡量不要用base64的方式來嵌入,因為大部分的郵件服務(Gmail)都不支援,如果是在單機上的郵件軟體就可能有支援,例如:Evolution.
                $conf["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();
                #$conf["levelForCheckSSL"],"字串",預設為"force",代表ssl一定要符合規範,"losse"代表先嘗試ssl要符合規範,若不符合則第2次就允許不符合規範的ssl,"none"代表直接允許不符合規範的ssl.
                $conf["levelForCheckSSL"]=$levelForCheckSSL;
                #範例語句:
                #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"){

                        #debug
                        var_dump($curlSmtpcurlSmtp);

                        #結束執行
                        exit;

                        }#if end

                #休息60秒
                sleep(60);

                #繼續執行
                continue;

                }#if end

        }#while end