Subversion Repositories php-qbpwcf

Rev

Rev 207 | Rev 239 | 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/>.

*/

/*
封鎖來自http、https、smtp、named的惡意ip.
*/

/*

bug log:

journalctl -a -e -f --unit=postfix

Mar 09 13:40:20 qbpwcf.org postfix/smtpd[1058247]: connect from unknown[194.48.251.15]
Mar 09 13:40:21 qbpwcf.org postfix/smtpd[1058247]: disconnect from unknown[194.48.251.15] ehlo=1 auth=0/1 quit=1 commands=2/3
Mar 09 13:40:45 qbpwcf.org postfix/smtpd[1050779]: connect from unknown[194.48.251.15]
Mar 09 13:40:46 qbpwcf.org postfix/smtpd[1050779]: disconnect from unknown[194.48.251.15] ehlo=1 auth=0/1 quit=1 commands=2/3
Mar 09 13:41:07 qbpwcf.org postfix/smtpd[1058247]: connect from unknown[194.48.251.15]
Mar 09 13:41:08 qbpwcf.org postfix/smtpd[1058247]: disconnect from unknown[194.48.251.15] ehlo=1 auth=0/1 quit=1 commands=2/3

Nov 18 01:42:38 qbpwcf.org postfix/smtpd[2800808]: warning: unknown[45.144.212.240]: SASL LOGIN authentication failed: Invalid authentication mechanism: 'LOGIN', sasl_username=(unavailable)

*/

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

#當前lib路徑
$pwd=$output[0];

#unix socket 的位置
$unixSocket=$pwd."/../../../var/qbpwcf/".basename(__FILE__).".sock";

#提示unix domain socket位置
echo "unix domain socket used at ".$unixSocket;

#初始化儲存上次各log的時間
$preTimeFloat=array();

#初始化記錄 http log 最後變更的時間
$preTimeFloat["http"]=0;

#初始化記錄 https log 最後變更的時間
$preTimeFloat["https"]=0;

#初始化記錄 smtpd log 最後變更的時間
$preTimeFloat["smtp"]=0;

#初始化記錄 dovecot/imap log 最後變更的時間
$preTimeFloat["imap"]=0;

#初始化記錄 named log 最後變更的時間
$preTimeFloat["named"]=0;

#初始化記錄 sshd log 最後變更的時間
$preTimeFloat["sshd"]=0;

#初始化不啟用debug模式
$debug=false;

#預設暫存的白名單ip有效時間為1小時
$tmp_white_ip_valid_time=1;

#說明函式
function help(){

        #印出指令說明
        echo "Usage of ".basename(__FILE__).":".PHP_EOL;
        echo "--debug [true/false] 代表是否要啟動 debug 模式".PHP_EOL;
        echo "--exclude [white list ip] 代表白名單IP,一次只能放一個IP.".PHP_EOL;
        echo "--tmp-white-ip-valid-time [white ip value time] 指定暫時白名單的有效小時".PHP_EOL;
        echo "--client [true/false] 代表是否為 client 端,而非 server 端".PHP_EOL;
        echo "--client-add-tmp-white-ip [while ip for while] client端指令,代表要增加的暫時白名單IP".PHP_EOL;
        echo "--client-update-tmp-white-ip-valid-time [white ip value time] client端指令,代表要更新暫時白名單的有效時間,單位為小時".PHP_EOL;

        #結束執行
        exit;

        }#function help 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"){

        #設置執行失敗
        $result["status"]="false";

        #設置錯誤訊息
        $result["error"]=$parseArgu;

        #印出結果
        var_dump($result);

        #結束執行
        exit(1);

        }#if end

#檢查參數
#函式說明:
#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
#回傳結果:
#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
#$result["error"],執行不正常結束的錯訊息陣列.
#$result["simpleError"],簡單表示的錯誤訊息.
#$result["function"],當前執行的函式名稱.
#$result["argu"],設置給予的參數.
#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
#$result["notNeedVar"],字串陣列,多餘的參數名稱.
#必填參數:
#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
$conf["varInput"]=&$parseArgu["content"];
#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
$conf["referenceVarKey"]="variableCheck::checkArguments";
#可省略參數:
#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
#$conf["mustBeFilledVariableName"]=array();
#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
#$conf["mustBeFilledVariableType"]=array();
#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
#$conf["canBeEmptyString"]="false";
#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
#$conf["canNotBeEmpty"]=array();
#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
#$conf["canBeEmpty"]=array();
#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
$conf["skipableVariableCanNotBeEmpty"]=array("debug","exclude","tmp-white-ip-valid-time","client","tmp-white-ip-valid-time","client-add-tmp-white-ip","client-update-tmp-white-ip-valid-time");
#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
$conf["skipableVariableName"]=array("debug","exclude","tmp-white-ip-valid-time","client","tmp-white-ip-valid-time","client-add-tmp-white-ip","client-update-tmp-white-ip-valid-time");
#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
$conf["skipableVariableType"]=array("array","array","array","array","array","array","array");
#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
$conf["skipableVarDefaultValue"]=array(array("false"),null,array("1"),null,null,null,null);
#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
$conf["disallowAllSkipableVarIsEmpty"]="false";
#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
$conf["disallowAllSkipableVarIsEmptyArray"]="false";
#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
#$conf["arrayCountEqualCheck"][]=array();
#參考資料:
#array_keys=>http://php.net/manual/en/function.array-keys.php
#備註:
#無.
$checkArguments=variableCheck::checkArguments($conf);
unset($conf);

#如果檢查參數失敗
if($checkArguments["status"]==="false"){

        #設置執行失敗
        $result["status"]="false";

        #設置錯誤訊息
        $result["error"]=$checkArguments;

        #印出結果
        var_dump($result);

        #結束執行,跟回傳錯誤代碼.
        exit(1);

        }#if end

#如果檢查參數不通過
if($checkArguments["passed"]==="false"){

        #設置執行失敗
        $result["status"]="false";

        #設置錯誤訊息
        $result["error"]=$checkArguments;

        #印出結果
        var_dump($result);

        #結束執行,跟回傳錯誤代碼.
        exit(1);

        }#if end

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

        #如果第一個參數為 "--debug true"
        if($parseArgu["content"]["debug"][0]==="true"){

                #設置debug模式
                $debug=true;

                #comment
                echo "debug mode".PHP_EOL;

                }#if end

        }#if end

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

        #預設沒有id
        $clientId="";

        #如果第一個參數為 "--client true"
        if($parseArgu["content"]["client"][0]==="true"){

                #函式說明:
                #連線到 unixDomainSockServer 提供的 unix domain socket.
                #回傳結果:
                #$result["status"],"true"代表執行正常;"false"代表執行不正常.
                #$result["error"],錯誤訊息陣列.
                #$result["function"],當前執行的函式名稱.
                #$result["content"],取得的回應.
                #必填參數:
                #$conf["sock"],字串,要連線的unix domain socket.
                $conf["sock"]=$unixSocket;
                #可省略參數:
                #$conf["id"],字串,取得的id,若無此值,則會得到新的數值.
                #$conf["id"]="";
                #$conf["cmd"],字串,要執行的指令,當$conf["id"]參數合法時,才會執行.
                #$conf["cmd"]="";
                #$conf["param"],參數陣列.
                #$conf["param"]=array();
                #$conf["escaped"],字串,param參數是否已經escaped了,預設為"false",反之為"true".
                #$conf["escaped"]="true";
                #$conf["custom"],陣列,要客制化傳輸的內容,會覆蓋以上除了$conf["id"]以外的可省略參數.
                #$conf["custom"]=array();
                #參考資料:
                #http://php.net/manual/en/function.stream-socket-client.php
                #http://php.net/manual/en/function.stream-get-contents.php
                #備註:
                #無.
                $unixDomainSockClient=sock::unixDomainSockClient($conf);
                unset($conf);

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

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$unixDomainSockClient;

                        #印出結果
                        var_dump($result);

                        #結束執行,跟回傳錯誤代碼.
                        exit(1);

                        }#if end

                #取得會應
                $res=$unixDomainSockClient["content"];

                #解析回應
                $res=(array)json_decode(trim($res));

                #debug
                #var_dump($res);

                #如果沒有給予 id
                if(!isset($res["id"])){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"][]="id not found";

                        #設置錯誤訊息
                        $result["error"][]=$res;

                        #印出結果
                        var_dump($result);

                        #結束執行,跟回傳錯誤代碼.
                        exit(1);

                        }#if end

                #取得用戶端的id
                $clientId=$res["id"];

                }#if end

        #如果有要增加暫時的白名單
        if(isset($parseArgu["content"]["client-add-tmp-white-ip"])){

                #針對每個要增加暫時的白名單
                foreach($parseArgu["content"]["client-add-tmp-white-ip"] as $tmpWhilteIp){

                        #要求 server 端增加暫時白名單 - start

                        #產生要傳遞的陣列
                        $request=array();

                        #設置要新增暫時白名單的ip
                        $request["add-tmp-white-ip"]=$tmpWhilteIp;

                        #函式說明:
                        #連線到 unixDomainSockServer 提供的 unix domain socket.
                        #回傳結果:
                        #$result["status"],"true"代表執行正常;"false"代表執行不正常.
                        #$result["error"],錯誤訊息陣列.
                        #$result["function"],當前執行的函式名稱.
                        #$result["content"],取得的回應.
                        #必填參數:
                        #$conf["sock"],字串,要連線的unix domain socket.
                        $conf["sock"]=$unixSocket;
                        #可省略參數:
                        #$conf["id"],字串,取得的id,若無此值,則會得到新的數值.
                        $conf["id"]=$clientId;
                        #$conf["cmd"],字串,要執行的指令,當$conf["id"]參數合法時,才會執行.
                        #$conf["cmd"]="";
                        #$conf["param"],參數陣列.
                        #$conf["param"]=array();
                        #$conf["escaped"],字串,param參數是否已經escaped了,預設為"false",反之為"true".
                        #$conf["escaped"]="true";
                        #$conf["custom"],陣列,要客制化傳輸的內容,會覆蓋以上除了$conf["id"]以外的可省略參數.
                        $conf["custom"]=$request;
                        #參考資料:
                        #http://php.net/manual/en/function.stream-socket-client.php
                        #http://php.net/manual/en/function.stream-get-contents.php
                        #備註:
                        #無.
                        $unixDomainSockClient=sock::unixDomainSockClient($conf);
                        unset($conf);

                        #debug
                        #var_dump($unixDomainSockClient);

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

                                #設置執行失敗
                                $result["status"]="false";

                                #設置錯誤訊息
                                $result["error"]=$unixDomainSockClient;

                                #印出結果
                                var_dump($result);

                                #結束執行,跟回傳錯誤代碼.
                                exit(1);

                                }#if end

                        #取得回應
                        $res=$unixDomainSockClient["content"];

                        #解析回應
                        $res=(array)json_decode(trim($res));

                        #要求 server 端增加暫時白名單 - end

                        }#foreach end

                }#if end

        #如果有要更新暫存白名單的有效時間
        if(isset($parseArgu["content"]["client-update-tmp-white-ip-valid-time"])){

                #要求 server 端更新暫時白名單的期限 - start

                #產生要傳遞的陣列
                $request=array();

                #設置要更新暫時白名單ip的有效時間
                $request["update-tmp-white-ip-valid-time"]=$parseArgu["content"]["client-update-tmp-white-ip-valid-time"][0];

                #函式說明:
                #連線到 unixDomainSockServer 提供的 unix domain socket.
                #回傳結果:
                #$result["status"],"true"代表執行正常;"false"代表執行不正常.
                #$result["error"],錯誤訊息陣列.
                #$result["function"],當前執行的函式名稱.
                #$result["content"],取得的回應.
                #必填參數:
                #$conf["sock"],字串,要連線的unix domain socket.
                $conf["sock"]=$unixSocket;
                #可省略參數:
                #$conf["id"],字串,取得的id,若無此值,則會得到新的數值.
                $conf["id"]=$clientId;
                #$conf["cmd"],字串,要執行的指令,當$conf["id"]參數合法時,才會執行.
                #$conf["cmd"]="";
                #$conf["param"],參數陣列.
                #$conf["param"]=array();
                #$conf["escaped"],字串,param參數是否已經escaped了,預設為"false",反之為"true".
                #$conf["escaped"]="true";
                #$conf["custom"],陣列,要客制化傳輸的內容,會覆蓋以上除了$conf["id"]以外的可省略參數.
                $conf["custom"]=$request;
                #參考資料:
                #http://php.net/manual/en/function.stream-socket-client.php
                #http://php.net/manual/en/function.stream-get-contents.php
                #備註:
                #無.
                $unixDomainSockClient=sock::unixDomainSockClient($conf);
                unset($conf);

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

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$unixDomainSockClient;

                        #印出結果
                        var_dump($result);

                        #結束執行,跟回傳錯誤代碼.
                        exit(1);

                        }#if end

                #取得回應
                $res=$unixDomainSockClient["content"];

                #解析回應
                $res=(array)json_decode(trim($res));

                #要求 server 端更新暫時白名單的期限 - end

                }#if end

        #client端程式結束,結束執行
        exit;

        }#if end

#取得自己對外的ip
#函式說明:
#依據提供查詢IP服務的網站取得伺服器對外的IP.
#回傳結果:
#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
#$result["function"],當前執行的函數名稱.
#$result["error"],錯誤訊息陣列.
#$result["content"],伺服端對外的IP.
#必填參數:
#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
$conf["fileArgu"]=__FILE__;
#可省略參數:
#無.
#備註:
#需要有網站支援此服務.
$getServerRealIP=csInformation::getServerRealIP($conf);
unset($conf);

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

        #設置執行失敗
        $result["status"]="false";

        #設置錯誤訊息
        $result["error"]=$getServerRealIP;

        #印出結果
        var_dump($result);

        #結束執行,跟回傳錯誤代碼.
        exit(1);

        }#if end

#預設的白名單為自己對外的IP
$excludeIp=array($getServerRealIP["content"]);

#提示內建白名單
echo "內建白名單:".$excludeIp[0].PHP_EOL;

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

        #針對每個白名單 IP
        foreach($parseArgu["content"]["exclude"] as $whiteIp){

                #提示內建白名單
                echo "附加白名單:".$whiteIp.PHP_EOL;

                #取得每個指定要排除的ip
                $excludeIp[]=$whiteIp;

                }#foreach end

        }#if end

#暫時的白名單
$excludeIpsTmp=array();

#函式說明:
#建立 unix domain socket server, 僅提供具備檔案存取權限的用戶使用,預設提供可以下達任何指令的功能.
#回傳結果:
#$result["status"],"true"代表執行正常;"false"代表執行不正常.
#$result["error"],錯誤訊息陣列.
#$result["function"],當前執行的函式名稱.
#必填參數:
#$conf["sock"],字串,socket檔案要放在哪邊,名稱為何.
$conf["sock"]=$unixSocket;
#$conf["fileArgu"],字串,變數__FILE__的內容.
$conf["fileArgu"]=__FILE__;
#可省略參數:
#$conf["changeOwner"],字串,要將socket檔案的擁有着權限進行修改."user.group"代表擁有者帳號為user,群組為group.
#$conf["changeOwner"]="";
#$conf["changePermission"],字串,要將socket檔案的權限設為多少.ex: 0666(所有帳戶都有存取的權限) 或 0660(僅有擁有者與群組帳戶有存取的權限) 或 0600(只有擁有者有權限執行).
$conf["changePermission"]="0666";
#$conf["sessionTimeout"],字串,當連線結束後於下一次連線間隔多久就算session timeout,server端會將記錄移除,client端需要重新拿取id,預設為300秒.
#$conf["sessionTimeout"]="300";
#$conf["addOnProcessFunc"],字串陣列,增加用於處理 json request 的函式名稱,給予的參數為array("request"=>收到的json訊息,"sock"=>用戶的socket).
$conf["addOnProcessFunc"]=array("\qbpwcf\addOnProcessFunc");
#$conf["funcToRunWhenIdle"],字串陣列,當沒有事件產生時,要執行的函式名稱,給予參數為array("client"=>所有用戶).
$conf["funcToRunWhenIdle"]=array("\qbpwcf\\funcToRunWhenIdle");
#$conf["infoToFunction"],陣列,需要增加給addOnProcessFunc跟funcToRunWhenIdle函式的資訊,在函式中其參數的info鍵值.
$conf["infoToFunction"]=array("debug"=>&$debug,"preTimeFloat"=>&$preTimeFloat,"excludeIpsTmp"=>&$excludeIpsTmp,"excludeIp"=>&$excludeIp,"tmp-white-ip-valid-time"=>&$tmp_white_ip_valid_time);
#參考資料:
#http://php.net/manual/en/function.stream-socket-server.php
#備註:
#無.
$unixDomainSockServer=sock::unixDomainSockServer($conf);
unset($conf);

#當執行失敗
if($unixDomainSockServer["status"]==="false"){

        #設置執行失敗
        $result["status"]="false";

        #設置錯誤訊息
        $result["error"]=$unixDomainSockServer;

        #印出結果
        var_dump($result);

        #結束執行,跟回傳錯誤代碼.
        exit(1);

        }#if end

#收到訊息要怎麼處理的函式
function addOnProcessFunc($params){

        #debug
        #var_dump(__LINE__,$params["request"]);

        #取得收到的訊息
        $receivedArray=$params["request"];

        #取得用戶的 socket
        $clientSock=$params["socket"];

        #預設不 debug
        $debug=false;

        #如果有debug鍵數值.
        if(isset($params["info"]["debug"])){

                #設置之
                $debug=$params["info"]["debug"];

                }#if end

        #debug mode
        if($debug){

                #debug
                var_dump(__LINE__,$params);

                }#if end

        #如果解析 json 失敗
        if(json_last_error()!==JSON_ERROR_NONE){

                #初始化結果
                $result=array();

                #設置執行失敗
                $result["status"]="false";

                #記錄錯誤訊息
                $result["error"]=json_last_error_msg();

                #回覆錯誤訊息
                fwrite($clientSock,json_encode($result).PHP_EOL);

                #初始化要回傳的訊息
                $result=array();

                #設置不繼續執行
                $result["continue"]="false";

                #回傳結果
                return $result;

                }#if end

        #debug mode
        if($debug){

                #debug
                var_dump(__LINE__,$receivedArray);

                }#if end

        #如果要新增暫時的ip白名單
        if(isset($receivedArray["add-tmp-white-ip"])){

                #函式說明:
                #將多個多維陣列串聯起來,key從0開始排序.
                #回傳的結果:
                #$result["status"],"true"表執行正常,"false"代表執行不正常.
                #$result["error"],錯誤訊息陣列.
                #$result["function"],當前執行的函數.
                #$result["content"],合併好的一維陣列.
                #必填參數
                #$conf["inputArray"],陣列,要合併的一維陣列變數,例如:=array($array1,$array2);
                $conf["inputArray"]=array($params["info"]["excludeIpsTmp"],array(array("ip"=>$receivedArray["add-tmp-white-ip"],"unixtime"=>time())));
                #可省略參數:
                #$conf["allowRepeat"],字串,預設為"false",不允許重複的結果;反之為"true".
                #$conf["allowRepeat"]="true";
                #$conf["equalKeyStruc"],字串陣列,若 allowRepeat 參數為 "false", 這該參數生效.該參數為用來判斷每個陣列的哪個鍵值路徑底下的數值相同時要進行取代,後者會取代前者.
                $conf["equalKeyStruc"]=array("ip");
                #參考資料:
                #無.
                #備註:
                #無.
                $mergeMultiDimensionArray=arrays::mergeMultiDimensionArray($conf);
                unset($conf);

                #debug mode
                if($debug){

                        #debug
                        var_dump(__LINE__,$mergeMultiDimensionArray);

                        }#if end

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

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$mergeMultiDimensionArray;

                        #印出結果
                        var_dump($result);

                        #結束執行
                        exit(1);

                        }#if end

                #更新白名單
                $params["info"]["excludeIpsTmp"]=$mergeMultiDimensionArray["content"];

                #debug mode
                if($debug){

                        #debug
                        var_dump(__LINE__,$params["info"]["excludeIpsTmp"]);

                        }#if end

                }#if end

        #反之收到 update-tmp-white-ip-valid-time
        if(isset($receivedArray["update-tmp-white-ip-valid-time"])){

                #更新白名單有效時間
                $params["info"]["tmp-white-ip-valid-time"]=$receivedArray["update-tmp-white-ip-valid-time"];

                #debug mode
                if($debug){

                        #debug
                        var_dump(__LINE__,$params["info"]["tmp-white-ip-valid-time"]);

                        }#if end

                }#if end

        #初始化要回傳的結果
        $result=array();

        #設置執行正常
        $result["status"]="true";

        #設置可以繼續執行後面的函式
        $result["continue"]="true";

        #回傳結果
        return $result;

        }#function addOnProcessFunc end

/*
#說明:
#沒事時要重複執行的函式
#參數:
#$params["info"]["preTimeFloat"]["http"],http log的最新時間.
#$params["info"]["preTimeFloat"]["https"],https log的最新時間.
#$params["info"]["preTimeFloat"]["smtp"],postfix.service log的最新時間.
#$params["info"]["preTimeFloat"]["imap"],dovecot.service log的最新時間.
#$params["info"]["preTimeFloat"]["named"],named.service log的最新時間.
#$params["info"]["preTimeFloat"]["sshd"],sshd.service log的最新時間.
*/
function funcToRunWhenIdle(&$params){

        #預設不 debug
        $debug=false;

        #如果有debug鍵數值.
        if(isset($params["info"]["debug"])){

                #設置之
                $debug=$params["info"]["debug"];

                }#if end

        #debug mode
        if($debug){

                #comment
                echo "new round".PHP_EOL;

                }#if end

        #debug mode
        if($debug){

                #comment
                echo "\$preHttpTimeFloat:".$params["info"]["preTimeFloat"]["http"].PHP_EOL;
                echo "\$preHttpsTimeFloat:".$params["info"]["preTimeFloat"]["https"].PHP_EOL;
                echo "\$preSmtpTimeFloat:".$params["info"]["preTimeFloat"]["smtp"].PHP_EOL;
                echo "\$preImapTimeFloat:".$params["info"]["preTimeFloat"]["imap"].PHP_EOL;
                echo "\$preNamedTimeFloat:".$params["info"]["preTimeFloat"]["named"].PHP_EOL;
                echo "\$preSshddTimeFloat:".$params["info"]["preTimeFloat"]["sshd"].PHP_EOL;

                }#if end

        #函式說明:
        #檢查多個檔案與資料夾是否存在.
        #回傳的結果:
        #$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$resutl["function"],當前執行的涵式名稱.
        #$result["argu"],使用的參數.
        #$result["allExist"],所有檔案皆存在的識別,"true"代表皆存在,"false"代表沒有全部都存在.
        #$result["varName"][$i],爲第$i個資料夾或檔案的路徑與名稱。
        #$result["varNameFullPath"][$i],爲第$i個資料夾或檔案的完整檔案系統路徑與名稱,如果不存在則代表路徑是網址.
        #$result["varNameWebPath"][$i],為第$i個資料夾或檔案的網址,若"web"參數為"true",才會有該內容.
        #$result["varExist"][$i],爲第$i個資料夾或檔案是否存在,"true"代表存在,"false"代表不存在。
        #必填參數:
        #$conf["fileArray"],陣列字串,要檢查是否存在的檔案有哪些,須爲一維陣列數值。
        $conf["fileAccess::checkMultiFileExist"]["fileArray"]=array("/var/log/httpd/access_log");
        #$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
        $conf["fileAccess::checkMultiFileExist"]["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["disableWebSearch"],"字串",是否取消「當檔案找不到時,改用catchWebContent類別的wget函數來檢查檔案是否存在於網路上」的功能,"false"不取消,若要取消該功能請設為"true",若抓到的內容為空字串則會視為檔案不存在,預設為"true".
        #$conf["disableWebSearch"]="false";
        #$conf["userDir"],字串,網頁是否置放於家目錄底下,"true"為是,"false"為不是,預設為"true".
        $conf["fileAccess::checkMultiFileExist"]["userDir"]="false";
        #$conf["web"],字串,檔案是放在web就是"true",反之為檔案系統"false",預設為"true".
        $conf["fileAccess::checkMultiFileExist"]["web"]="false";
        #參考資料:
        #http://php.net/manual/en/function.file-exists.php
        #http://php.net/manual/en/control-structures.foreach.php
        #備註:
        #函數file_exists檢查的路徑為檔案系統的路徑
        #$result["varName"][$i]結果未實作
        $checkMultiFileExist=fileAccess::checkMultiFileExist($conf["fileAccess::checkMultiFileExist"]);
        unset($conf["fileAccess::checkMultiFileExist"]);

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

                #設置執行失敗
                $result["status"]="false";

                #設置錯誤訊息
                $result["error"]=$checkMultiFileExist;

                #印出結果
                var_dump($checkMultiFileExist);

                #結束執行
                exit(1);

                }#if end

        #如果存在 http log
        if($checkMultiFileExist["allExist"]==="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["content"],為執行完後的輸出字串.
                #$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.
                #$result["running"],是否還在執行.
                #$result["pid"],pid.
                #$result["statusCode"],執行結束後的代碼.
                #$result["escape"],陣列,儲存重新排序過且已經escape過的指令(key為"cmd")與參數(key為"argu")與兩者組合的一維陣列(key為"array").
                #$result["noEcaped"],陣列,儲存重新排序過未經過escape過的指令(key為"cmd")與參數(key為"argu")與兩者組合的一維陣列(key為"array").
                #必填參數:
                #$conf["command"],字串,要執行的指令.
                $conf["external::callShell"]["command"]="tail";
                #$conf["fileArgu"],字串,變數__FILE__的內容.
                $conf["external::callShell"]["fileArgu"]=__FILE__;
                #可省略參數:
                #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
                $conf["external::callShell"]["argu"]=array("-n","1","/var/log/httpd/access_log");
                #$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".如果參數為"< 、<< 、> 、>> 、| 、2>&1"之一則不會過濾.
                $conf["external::callShell"]["escapeshellarg"]="true";
                #$conf["thereIsShellVar"],陣列字串,指令搭配的參數"argu",若含有「\'」,則取代為「"」.每個argu參數都要有對應的元素."true"代表要置換.
                #$conf["thereIsShellVar"]=array();
                #$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";
                #$conf["doNotRun"],字串,"true"代表不執行指令,預設為"false"會執行指令.
                #$conf["doNotRun"]="false";
                #參考資料:
                #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
                #備註:
                #不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.
                #若使用的 command、argu 參數,含有 ~ 則會被視為字串,若有需要其於 shell 中代表的家目錄位置,可用 fileAccess::tildeToPath 來進行轉換.
                $callShell=external::callShell($conf["external::callShell"]);
                unset($conf["external::callShell"]);

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

                        #debug
                        var_dump($callShell);

                        #結束並回傳代表1,表示異常
                        exit(1);

                        }#if end

                #如果輸出有一行
                if(count($callShell["output"])===1){

                        #debug
                        if($debug){

                                #標題提示
                                echo "最新一筆log".PHP_EOL;

                                #印出log
                                echo $callShell["output"][0].PHP_EOL;

                                }#if end

                        #範例log
                        #193.42.43.36 - - [30/Sep/2025:13:15:04 +0800] "GET / HTTP/2.0" 200 138772
                        #${ip} ${doNotNeed} [${day}/${month}/${year}:${hour}:${min}:${sec} ${timezone}] ${method} ${path} ${protocol} ${responseCode} ${bytesSend}

                        #解析時間
                        #函式說明:
                        #尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.
                        #回傳結果:
                        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                        #$reuslt["error"],執行不正常結束的錯訊息陣列.
                        #$result["function"],當前執行的函式名稱.
                        #$result["argu"],所使用的參數.
                        #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                        #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                        #$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.
                        #必填參數:
                        #$conf["input"],字串,要檢查的字串.
                        $conf["search::findSpecifyStrFormat"]["input"]=$callShell["output"][0];
                        #$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                        $conf["search::findSpecifyStrFormat"]["format"]="\${ip} \${doNotNeed} [\${day}/\${month}/\${year}:\${hour}:\${min}:\${sec} \${timezone}] \${method} \${path} \${protocol} \${responseCode} \${bytesSend}";
                        #可省略參數:
                        #$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.
                        #$conf["varEqual"]=array(null,"found");
                        #$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.
                        #$conf["varCon"]=array("no_tail"=>" not");
                        #參考資料:
                        #無.
                        #備註:
                        #無.
                        $findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);
                        unset($conf["search::findSpecifyStrFormat"]);

                        #如果執行異常
                        if($findSpecifyStrFormat["status"]==="false"){

                                #debug
                                var_dump($findSpecifyStrFormat);

                                #結束並回傳代表1,表示異常
                                exit(1);

                                }#if end

                        #如果格式有符合
                        if($findSpecifyStrFormat["found"]==="true"){

                                #記錄 http log 的最後變更時間
                                $httpTimeFloat=strtotime($findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0]);

                                }#if end

                        }#if end

                        #反之沒變動
                        else{

                                #沿用上次時間
                                $httpTimeFloat=$params["info"]["preTimeFloat"]["http"];

                                }#else ebd

                #debug
                if($debug){

                        #comment
                        echo "accessed file /var/log/httpd/access_log".PHP_EOL;

                        }#if end

                }#if end

        #函式說明:
        #檢查多個檔案與資料夾是否存在.
        #回傳的結果:
        #$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$resutl["function"],當前執行的涵式名稱.
        #$result["argu"],使用的參數.
        #$result["allExist"],所有檔案皆存在的識別,"true"代表皆存在,"false"代表沒有全部都存在.
        #$result["varName"][$i],爲第$i個資料夾或檔案的路徑與名稱。
        #$result["varNameFullPath"][$i],爲第$i個資料夾或檔案的完整檔案系統路徑與名稱,如果不存在則代表路徑是網址.
        #$result["varNameWebPath"][$i],為第$i個資料夾或檔案的網址,若"web"參數為"true",才會有該內容.
        #$result["varExist"][$i],爲第$i個資料夾或檔案是否存在,"true"代表存在,"false"代表不存在。
        #必填參數:
        #$conf["fileArray"],陣列字串,要檢查是否存在的檔案有哪些,須爲一維陣列數值。
        $conf["fileAccess::checkMultiFileExist"]["fileArray"]=array("/var/log/httpd/ssl_access_log");
        #$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
        $conf["fileAccess::checkMultiFileExist"]["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["disableWebSearch"],"字串",是否取消「當檔案找不到時,改用catchWebContent類別的wget函數來檢查檔案是否存在於網路上」的功能,"false"不取消,若要取消該功能請設為"true",若抓到的內容為空字串則會視為檔案不存在,預設為"true".
        #$conf["disableWebSearch"]="false";
        #$conf["userDir"],字串,網頁是否置放於家目錄底下,"true"為是,"false"為不是,預設為"true".
        $conf["fileAccess::checkMultiFileExist"]["userDir"]="false";
        #$conf["web"],字串,檔案是放在web就是"true",反之為檔案系統"false",預設為"true".
        $conf["fileAccess::checkMultiFileExist"]["web"]="false";
        #參考資料:
        #http://php.net/manual/en/function.file-exists.php
        #http://php.net/manual/en/control-structures.foreach.php
        #備註:
        #函數file_exists檢查的路徑為檔案系統的路徑
        #$result["varName"][$i]結果未實作
        $checkMultiFileExist=fileAccess::checkMultiFileExist($conf["fileAccess::checkMultiFileExist"]);
        unset($conf["fileAccess::checkMultiFileExist"]);

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

                #設置執行失敗
                $result["status"]="false";

                #設置錯誤訊息
                $result["error"]=$checkMultiFileExist;

                #印出結果
                var_dump($checkMultiFileExist);

                #結束執行
                exit(1);

                }#if end

        #如果存在 https log
        if($checkMultiFileExist["allExist"]==="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["content"],為執行完後的輸出字串.
                #$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.
                #$result["running"],是否還在執行.
                #$result["pid"],pid.
                #$result["statusCode"],執行結束後的代碼.
                #$result["escape"],陣列,儲存重新排序過且已經escape過的指令(key為"cmd")與參數(key為"argu")與兩者組合的一維陣列(key為"array").
                #$result["noEcaped"],陣列,儲存重新排序過未經過escape過的指令(key為"cmd")與參數(key為"argu")與兩者組合的一維陣列(key為"array").
                #必填參數:
                #$conf["command"],字串,要執行的指令.
                $conf["external::callShell"]["command"]="tail";
                #$conf["fileArgu"],字串,變數__FILE__的內容.
                $conf["external::callShell"]["fileArgu"]=__FILE__;
                #可省略參數:
                #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
                $conf["external::callShell"]["argu"]=array("-n","1","/var/log/httpd/ssl_access_log");
                #$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".如果參數為"< 、<< 、> 、>> 、| 、2>&1"之一則不會過濾.
                $conf["external::callShell"]["escapeshellarg"]="true";
                #$conf["thereIsShellVar"],陣列字串,指令搭配的參數"argu",若含有「\'」,則取代為「"」.每個argu參數都要有對應的元素."true"代表要置換.
                #$conf["thereIsShellVar"]=array();
                #$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";
                #$conf["doNotRun"],字串,"true"代表不執行指令,預設為"false"會執行指令.
                #$conf["doNotRun"]="false";
                #參考資料:
                #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
                #備註:
                #不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.
                #若使用的 command、argu 參數,含有 ~ 則會被視為字串,若有需要其於 shell 中代表的家目錄位置,可用 fileAccess::tildeToPath 來進行轉換.
                $callShell=external::callShell($conf["external::callShell"]);
                unset($conf["external::callShell"]);

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

                        #debug
                        var_dump($callShell);

                        #結束並回傳代表1,表示異常
                        exit(1);

                        }#if end

                #如果輸出有一行
                if(count($callShell["output"])===1){

                        #debug
                        if($debug){

                                #標題提示
                                echo "最新一筆log".PHP_EOL;

                                #印出log
                                echo $callShell["output"][0].PHP_EOL;

                                }#if end

                        #範例log
                        #193.42.43.36 - - [30/Sep/2025:13:15:04 +0800] "GET / HTTP/2.0" 200 138772
                        #${ip} ${doNotNeed} [${day}/${month}/${year}:${hour}:${min}:${sec} ${timezone}] ${method} ${path} ${protocol} ${responseCode} ${bytesSend}

                        #解析時間
                        #函式說明:
                        #尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.
                        #回傳結果:
                        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                        #$reuslt["error"],執行不正常結束的錯訊息陣列.
                        #$result["function"],當前執行的函式名稱.
                        #$result["argu"],所使用的參數.
                        #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                        #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                        #$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.
                        #必填參數:
                        #$conf["input"],字串,要檢查的字串.
                        $conf["input"]=$callShell["output"][0];
                        #$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                        $conf["format"]="\${ip} \${doNotNeed} [\${day}/\${month}/\${year}:\${hour}:\${min}:\${sec} \${timezone}] \${method} \${path} \${protocol} \${responseCode} \${bytesSend}";
                        #可省略參數:
                        #$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.
                        #$conf["varEqual"]=array(null,"found");
                        #$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.
                        #$conf["varCon"]=array("no_tail"=>" not");
                        #參考資料:
                        #無.
                        #備註:
                        #無.
                        $findSpecifyStrFormat=search::findSpecifyStrFormat($conf);
                        unset($conf);

                        #如果執行異常
                        if($findSpecifyStrFormat["status"]==="false"){

                                #debug
                                var_dump($findSpecifyStrFormat);

                                #結束並回傳代表1,表示異常
                                exit(1);

                                }#if end

                        #如果格式有符合
                        if($findSpecifyStrFormat["found"]==="true"){

                                #記錄 http log 的最後變更時間
                                $httpsTimeFloat=strtotime($findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0]);

                                }#if end

                        }#if end

                #反之沒變動
                else{

                        #沿用上次時間
                        $httpsTimeFloat=$params["info"]["preTimeFloat"]["https"];

                        }#else ebd

                #debug
                if($debug){

                        #comment
                        echo "accessed file /var/log/httpd/ssl_access_log".PHP_EOL;

                        }#if end

                }#if end

        #透過運行以下指令取得最後變更時間
        #journalctl -a -e --unit=postfix.service | tail -n 1;
        #涵式說明:
        #呼叫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["external::callShell"]["command"]="journalctl";
        #$conf["fileArgu"],字串,變數__FILE__的內容.
        $conf["external::callShell"]["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
        $conf["external::callShell"]["argu"]=array("-a","-e","--unit=postfix.service","|","tail","-n","1");
        #$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["external::callShell"]["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["external::callShell"]);
        unset($conf["external::callShell"]);

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

                #設置執行失敗
                $result["status"]="false";

                #設置錯誤訊息
                $result["error"]=$callShell;

                #回傳結果
                var_dump($result);

                #結束執行
                exit(1);

                }#if end

        #debug
        if($debug){

                #comment
                echo "accessed file postfix/smtp log".PHP_EOL;

                }#if end

        #取得行數
        $lineCount=count($callShell["output"]);

        #函式說明:
        #多層if判斷.
        #回傳結果:
        #$result["status"],字串,"true"代表執行正常;"false"代表執行異常.
        #$result["function"],當前函式的名稱.
        #$result["pass"],字串,"true"代表通過多層if判斷;反之為"false".
        #必填參數:
        #$conf["get_defined_vars"],陣列,所有已經定義的變數.
        $conf["controlStructures::nestedIf"]["get_defined_vars"]=get_defined_vars();
        #$conf["varToControlLeft"],變數陣列,依照順序每層要做判斷的變數.
        $conf["controlStructures::nestedIf"]["varToControlLeft"]=array("lineCount",array("callShell","output",0));
        #$conf["conditions"],字串陣列,依照順序每層變數判斷的條件,例如">","<",">=","<=","!=","==","<==","!==","===".
        $conf["controlStructures::nestedIf"]["conditions"]=array("===","!==");
        #$conf["varToControlRight"],變數陣列,依照順序每層變數判斷期望的結果.
        $conf["controlStructures::nestedIf"]["varToControlRight"]=array(1,"-- No entries --");
        #可省略參數:
        #無.
        #參考資料:
        #無.
        #備註:
        #無.
        $nestedIf=controlStructures::nestedIf($conf["controlStructures::nestedIf"]);
        unset($conf["controlStructures::nestedIf"]);

        #如果執行異常
        if($nestedIf["status"]==="false"){

                #設置執行異常
                $result["status"]="false";

                #設置執行錯誤
                $result["error"]=$nestedIf;

                #回傳結果
                return $result;

                }#if end

        #如果不通過判斷
        if($nestedIf["pass"]==="false"){

                #沿用上次時間
                $smtpTimeFloat=$params["info"]["preTimeFloat"]["smtp"];

                }#if end

        #反之
        else{

                #debug
                if($debug){

                        #標題提示
                        echo "最新一筆log".PHP_EOL;

                        #印出log
                        echo $callShell["output"][0].PHP_EOL;

                        }#if end

                #Aug 09 07:12:09 www.qbpwcf.org postfix/smtpd[20829]: connect from unknown[185.234.219.62]
                #Apr 04 15:11:16 mail.qbpwcf.org postfix/smtps/smtpd[10145]: connect from unknown[212.70.149.72]
                #Nov 18 01:42:38 qbpwcf.org postfix/smtpd[2800808]: warning: unknown[45.144.212.240]: SASL LOGIN authentication failed: Invalid authentication mechanism: 'LOGIN', sasl_username=(unavailable)
                #${month} ${day} ${hour}:${min}:${sec} ${doNotNeed}"

                #解析時間點
                #函式說明:
                #尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.
                #回傳結果:
                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                #$reuslt["error"],執行不正常結束的錯訊息陣列.
                #$result["function"],當前執行的函式名稱.
                #$result["argu"],所使用的參數.
                #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                #$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.
                #必填參數:
                #$conf["input"],字串,要檢查的字串.
                $conf["search::findSpecifyStrFormat"]["input"]=$callShell["output"][0];
                #$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                $conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed}";
                #可省略參數:
                #$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.
                #$conf["varEqual"]=array(null,"found");
                #$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.
                #$conf["varCon"]=array("no_tail"=>" not");
                #參考資料:
                #無.
                #備註:
                #無.
                $findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);
                unset($conf["search::findSpecifyStrFormat"]);

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

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$findSpecifyStrFormat;

                        #回傳結果
                        var_dump($result);

                        #結束執行
                        exit(1);

                        }#if end

                #如果log沒有時間戳記
                if($findSpecifyStrFormat["found"]==="false"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$findSpecifyStrFormat;

                        #回傳結果
                        var_dump($result);

                        #結束執行
                        exit(1);

                        }#if end

                #記錄 smtpd log 最後變更的時間
                $smtpTimeFloat=strtotime($findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0]);

                }#if end

        #透過運行以下指令取得最後變更時間
        #journalctl -a -e --unit=dovecot.service | tail -n 1
        #涵式說明:
        #呼叫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["external::callShell"]["command"]="journalctl";
        #$conf["fileArgu"],字串,變數__FILE__的內容.
        $conf["external::callShell"]["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
        $conf["external::callShell"]["argu"]=array("-a","-e","--unit=dovecot.service","|","tail","-n","1");
        #$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["external::callShell"]["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["external::callShell"]);
        unset($conf["external::callShell"]);

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

                #設置執行失敗
                $result["status"]="false";

                #設置錯誤訊息
                $result["error"]=$callShell;

                #回傳結果
                var_dump($result);

                #結束執行
                exit(1);

                }#if end

        #debug
        if($debug){

                #comment
                echo "accessed file dovecot/imap log".PHP_EOL;

                }#if end

        #取得行數
        $lineCount=count($callShell["output"]);

        #函式說明:
        #多層if判斷.
        #回傳結果:
        #$result["status"],字串,"true"代表執行正常;"false"代表執行異常.
        #$result["function"],當前函式的名稱.
        #$result["pass"],字串,"true"代表通過多層if判斷;反之為"false".
        #必填參數:
        #$conf["get_defined_vars"],陣列,所有已經定義的變數.
        $conf["controlStructures::nestedIf"]["get_defined_vars"]=get_defined_vars();
        #$conf["varToControlLeft"],變數陣列,依照順序每層要做判斷的變數.
        $conf["controlStructures::nestedIf"]["varToControlLeft"]=array("lineCount",array("callShell","output",0));
        #$conf["conditions"],字串陣列,依照順序每層變數判斷的條件,例如">","<",">=","<=","!=","==","<==","!==","===".
        $conf["controlStructures::nestedIf"]["conditions"]=array("===","!==");
        #$conf["varToControlRight"],變數陣列,依照順序每層變數判斷期望的結果.
        $conf["controlStructures::nestedIf"]["varToControlRight"]=array(1,"-- No entries --");
        #可省略參數:
        #無.
        #參考資料:
        #無.
        #備註:
        #無.
        $nestedIf=controlStructures::nestedIf($conf["controlStructures::nestedIf"]);
        unset($conf["controlStructures::nestedIf"]);

        #如果執行異常
        if($nestedIf["status"]==="false"){

                #設置執行異常
                $result["status"]="false";

                #設置執行錯誤
                $result["error"]=$nestedIf;

                #回傳結果
                return $result;

                }#if end

        #如果不通過判斷
        if($nestedIf["pass"]==="false"){

                #沿用上次時間
                $imapTimeFloat=$params["info"]["preTimeFloat"]["imap"];

                }#if end

        #反之
        else{

                #debug
                if($debug){

                        #標題提示
                        echo "最新一筆log".PHP_EOL;

                        #印出log
                        echo $callShell["output"][0].PHP_EOL;

                        }#if end

                #Feb 23 07:44:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<9oMMYvW7ihhliNc9>
                #${month} ${day} ${hour}:${min}:${sec} ${doNotNeed}"

                #解析時間點
                #函式說明:
                #尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.
                #回傳結果:
                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                #$reuslt["error"],執行不正常結束的錯訊息陣列.
                #$result["function"],當前執行的函式名稱.
                #$result["argu"],所使用的參數.
                #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                #$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.
                #必填參數:
                #$conf["input"],字串,要檢查的字串.
                $conf["search::findSpecifyStrFormat"]["input"]=$callShell["output"][0];
                #$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                $conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed}";
                #可省略參數:
                #$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.
                #$conf["varEqual"]=array(null,"found");
                #$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.
                #$conf["varCon"]=array("no_tail"=>" not");
                #參考資料:
                #無.
                #備註:
                #無.
                $findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);
                unset($conf["search::findSpecifyStrFormat"]);

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

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$findSpecifyStrFormat;

                        #回傳結果
                        var_dump($result);

                        #結束執行
                        exit(1);

                        }#if end

                #如果log沒有時間戳記
                if($findSpecifyStrFormat["found"]==="false"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$findSpecifyStrFormat;

                        #回傳結果
                        var_dump($result);

                        #結束執行
                        exit(1);

                        }#if end

                #記錄 dovecot log 最後變更的時間
                $imapTimeFloat=strtotime($findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0]);

                }#if end

        #透過 journalctl -a -e --unit=named.service | tail -n 1 來取得最後一筆 dns 查詢記錄
        #涵式說明:
        #呼叫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["external::callShell"]["command"]="journalctl";
        #$conf["fileArgu"],字串,變數__FILE__的內容.
        $conf["external::callShell"]["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
        $conf["external::callShell"]["argu"]=array("-a","-e","--unit=named.service","|","tail","-n","1");
        #$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["external::callShell"]["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["external::callShell"]);
        unset($conf["external::callShell"]);

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

                #設置執行失敗
                $result["status"]="false";

                #設置錯誤訊息
                $result["error"]=$callShell;

                #回傳結果
                var_dump($result);

                #結束執行
                exit(1);

                }#if end

        #debug
        if($debug){

                #comment
                echo "accessed file named log".PHP_EOL;

                }#if end

        #取得行數
        $lineCount=count($callShell["output"]);

        #函式說明:
        #多層if判斷.
        #回傳結果:
        #$result["status"],字串,"true"代表執行正常;"false"代表執行異常.
        #$result["function"],當前函式的名稱.
        #$result["pass"],字串,"true"代表通過多層if判斷;反之為"false".
        #必填參數:
        #$conf["get_defined_vars"],陣列,所有已經定義的變數.
        $conf["controlStructures::nestedIf"]["get_defined_vars"]=get_defined_vars();
        #$conf["varToControlLeft"],變數陣列,依照順序每層要做判斷的變數.
        $conf["controlStructures::nestedIf"]["varToControlLeft"]=array("lineCount",array("callShell","output",0));
        #$conf["conditions"],字串陣列,依照順序每層變數判斷的條件,例如">","<",">=","<=","!=","==","<==","!==","===".
        $conf["controlStructures::nestedIf"]["conditions"]=array("===","!==");
        #$conf["varToControlRight"],變數陣列,依照順序每層變數判斷期望的結果.
        $conf["controlStructures::nestedIf"]["varToControlRight"]=array(1,"-- No entries --");
        #可省略參數:
        #無.
        #參考資料:
        #無.
        #備註:
        #無.
        $nestedIf=controlStructures::nestedIf($conf["controlStructures::nestedIf"]);
        unset($conf["controlStructures::nestedIf"]);

        #如果執行異常
        if($nestedIf["status"]==="false"){

                #設置執行異常
                $result["status"]="false";

                #設置執行錯誤
                $result["error"]=$nestedIf;

                #回傳結果
                return $result;

                }#if end

        #如果不通過判斷
        if($nestedIf["pass"]==="false"){

                #沿用上次的時間
                $namedTimeFloat=$params["info"]["preTimeFloat"]["named"];

                }#if end

        #反之
        else{

                #debug
                if($debug){

                        #標題提示
                        echo "最新一筆log".PHP_EOL;

                        #印出log
                        echo $callShell["output"][0].PHP_EOL;

                        }#if end

                #Nov 24 20:55:15 localhost.localdomain named[99512]: client @0x7f7714041d10 191.7.219.100#6238 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                #${month} ${day} ${hour}:${min}:${sec} ${doNotNeed}

                #解析時間點
                #函式說明:
                #尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.
                #回傳結果:
                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                #$reuslt["error"],執行不正常結束的錯訊息陣列.
                #$result["function"],當前執行的函式名稱.
                #$result["argu"],所使用的參數.
                #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                #$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.
                #必填參數:
                #$conf["input"],字串,要檢查的字串.
                $conf["search::findSpecifyStrFormat"]["input"]=$callShell["output"][0];
                #$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                $conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed}";
                #可省略參數:
                #$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.
                #$conf["varEqual"]=array(null,"found");
                #$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.
                #$conf["varCon"]=array("no_tail"=>" not");
                #參考資料:
                #無.
                #備註:
                #無.
                $findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);
                unset($conf["search::findSpecifyStrFormat"]);

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

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$findSpecifyStrFormat;

                        #回傳結果
                        var_dump($result);

                        #結束執行
                        exit(1);

                        }#if end

                #如果log沒有時間戳記
                if($findSpecifyStrFormat["found"]==="false"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$findSpecifyStrFormat;

                        #回傳結果
                        var_dump($result);

                        #結束執行
                        exit(1);

                        }#if end

                #記錄 named log 最後變更的時間
                $namedTimeFloat=strtotime($findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0]);

                }#else end

        #透過 journalctl -a -e --unit=sshd.service | tail -n 1 來取得最後一筆 dns 查詢記錄
        #涵式說明:
        #呼叫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["external::callShell"]["command"]="journalctl";
        #$conf["fileArgu"],字串,變數__FILE__的內容.
        $conf["external::callShell"]["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
        $conf["external::callShell"]["argu"]=array("-a","-e","--unit=sshd.service","|","tail","-n","1");
        #$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["external::callShell"]["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["external::callShell"]);
        unset($conf["external::callShell"]);

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

                #設置執行失敗
                $result["status"]="false";

                #設置錯誤訊息
                $result["error"]=$callShell;

                #回傳結果
                var_dump($result);

                #結束執行
                exit(1);

                }#if end

        #debug
        if($debug){

                #comment
                echo "accessed sshd log".PHP_EOL;

                }#if end

        #取得行數
        $lineCount=count($callShell["output"]);

        #debug
        #var_dump(__LINE__,get_defined_vars()["lineCount"],get_defined_vars()["callShell"]["output"]);

        #函式說明:
        #多層if判斷.
        #回傳結果:
        #$result["status"],字串,"true"代表執行正常;"false"代表執行異常.
        #$result["function"],當前函式的名稱.
        #$result["pass"],字串,"true"代表通過多層if判斷;反之為"false".
        #必填參數:
        #$conf["get_defined_vars"],陣列,所有已經定義的變數.
        $conf["controlStructures::nestedIf"]["get_defined_vars"]=get_defined_vars();
        #$conf["varToControlLeft"],變數陣列,依照順序每層要做判斷的變數.
        $conf["controlStructures::nestedIf"]["varToControlLeft"]=array("lineCount",array("callShell","output",0));
        #$conf["conditions"],字串陣列,依照順序每層變數判斷的條件,例如">","<",">=","<=","!=","==","<==","!==","===".
        $conf["controlStructures::nestedIf"]["conditions"]=array("===","!==");
        #$conf["varToControlRight"],變數陣列,依照順序每層變數判斷期望的結果.
        $conf["controlStructures::nestedIf"]["varToControlRight"]=array(1,"-- No entries --");
        #可省略參數:
        #無.
        #參考資料:
        #無.
        #備註:
        #無.
        $nestedIf=controlStructures::nestedIf($conf["controlStructures::nestedIf"]);
        unset($conf["controlStructures::nestedIf"]);

        #如果執行異常
        if($nestedIf["status"]==="false"){

                #設置執行異常
                $result["status"]="false";

                #設置執行錯誤
                $result["error"]=$nestedIf;

                #回傳結果
                return $result;

                }#if end

        #debug
        #var_dump(__LINE__,$nestedIf["pass"]);

        #如果不通過判斷
        if($nestedIf["pass"]==="false"){

                #debug
                var_dump(__LINE__,$nestedIf["reason"]);

                #沿用上次的時間
                $sshdTimeFloat=$params["info"]["preTimeFloat"]["sshd"];

                }#if end

        #反之
        else{

                #debug
                if($debug){

                        #標題提示
                        echo "最新一筆log".PHP_EOL;

                        #印出log
                        echo $callShell["output"][0].PHP_EOL;

                        }#if end

                #Sep 30 00:36:36 silverblue-guest.qbpwcf.org sshd-session[1607010]: Invalid user lizepeng from 60.213.10.69 port 39156
                #${month} ${day} ${hour}:${min}:${sec} ${doNotNeed}

                #解析時間點
                #函式說明:
                #尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.
                #回傳結果:
                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                #$reuslt["error"],執行不正常結束的錯訊息陣列.
                #$result["function"],當前執行的函式名稱.
                #$result["argu"],所使用的參數.
                #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                #$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.
                #必填參數:
                #$conf["input"],字串,要檢查的字串.
                $conf["search::findSpecifyStrFormat"]["input"]=$callShell["output"][0];
                #$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                $conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed}";
                #可省略參數:
                #$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.
                #$conf["varEqual"]=array(null,"found");
                #$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.
                #$conf["varCon"]=array("no_tail"=>" not");
                #參考資料:
                #無.
                #備註:
                #無.
                $findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);
                unset($conf["search::findSpecifyStrFormat"]);

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

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$findSpecifyStrFormat;

                        #回傳結果
                        var_dump($result);

                        #結束執行
                        exit(1);

                        }#if end

                #如果log沒有時間戳記
                if($findSpecifyStrFormat["found"]==="false"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$findSpecifyStrFormat;

                        #回傳結果
                        var_dump($result);

                        #結束執行
                        exit(1);

                        }#if end

                #記錄 sshd log 最後變更的時間
                $sshdTimeFloat=strtotime($findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0]);

                }#else end

        #debug mode
        if($debug){

                #comment
                echo "\$httpTimeFloat:".$httpTimeFloat.PHP_EOL;
                echo "\$httpsTimeFloat:".$httpsTimeFloat.PHP_EOL;
                echo "\$smtpTimeFloat:".$smtpTimeFloat.PHP_EOL;
                echo "\$imapTimeFloat:".$imapTimeFloat.PHP_EOL;
                echo "\$namedTimeFloat:".$namedTimeFloat.PHP_EOL;
                echo "\$sshdTimeFloat:".$sshdTimeFloat.PHP_EOL;

                }#if end

        #第一次運行,不做事.
        if($params["info"]["preTimeFloat"]["http"]===0 && $params["info"]["preTimeFloat"]["https"]===0 && $params["info"]["preTimeFloat"]["smtp"]===0 && $params["info"]["preTimeFloat"]["imap"]===0 && $params["info"]["preTimeFloat"]["named"]===0){

                #將本次http記錄覆寫到上次的記錄
                $params["info"]["preTimeFloat"]["http"]=$httpTimeFloat;

                #將本次https記錄覆寫到上次的記錄
                $params["info"]["preTimeFloat"]["https"]=$httpsTimeFloat;

                #將本次smtps記錄覆寫到上次的記錄
                $params["info"]["preTimeFloat"]["smtp"]=$smtpTimeFloat;

                #將本次imaps記錄覆寫到上次的記錄
                $params["info"]["preTimeFloat"]["imap"]=$imapTimeFloat;

                #將本次nmaed記錄覆寫到上次的記錄
                $params["info"]["preTimeFloat"]["named"]=$namedTimeFloat;

                #將本次sshd記錄覆寫到上次的記錄
                $params["info"]["preTimeFloat"]["sshd"]=$sshdTimeFloat;

                #睡一秒
                sleep(1);

                #debug mode
                if($debug){

                        #comment
                        echo "第一次運行,不做事".PHP_EOL;

                        }#if end

                #結束執行
                return;

                }#if end

        #非第一次運行,且 http 與 https 與 imap 與 smtp 與 named log 都沒變動過.
        else if($params["info"]["preTimeFloat"]["http"]===$httpTimeFloat && $params["info"]["preTimeFloat"]["https"]===$httpsTimeFloat && $params["info"]["preTimeFloat"]["smtp"]===$smtpTimeFloat && $params["info"]["preTimeFloat"]["imap"]===$imapTimeFloat && $params["info"]["preTimeFloat"]["named"]===$namedTimeFloat && $params["info"]["preTimeFloat"]["sshd"]===$sshdTimeFloat){

                #睡一秒
                sleep(1);

                #debug mode
                if($debug){

                        #comment
                        echo "Log檔無變動,不做事".PHP_EOL;

                        }#if end

                #結束執行
                return;

                }#else end

        #debug mode
        if($debug){

                #comment
                echo "Log檔有變動,要做事".PHP_EOL;
                echo "\$preHttpTimeFloat:".$params["info"]["preTimeFloat"]["http"].PHP_EOL;
                echo "\$preHttpsTimeFloat:".$params["info"]["preTimeFloat"]["https"].PHP_EOL;
                echo "\$preSmtpTimeFloat:".$params["info"]["preTimeFloat"]["smtp"].PHP_EOL;
                echo "\$preImapTimeFloat:".$params["info"]["preTimeFloat"]["imap"].PHP_EOL;
                echo "\$preNamedTimeFloat:".$params["info"]["preTimeFloat"]["named"].PHP_EOL;
                echo "\$preSshdTimeFloat:".$params["info"]["preTimeFloat"]["sshd"].PHP_EOL;
                echo "\$httpTimeFloat:".$httpTimeFloat.PHP_EOL;
                echo "\$httpsTimeFloat:".$httpsTimeFloat.PHP_EOL;
                echo "\$smtpTimeFloat:".$smtpTimeFloat.PHP_EOL;
                echo "\$imapTimeFloat:".$imapTimeFloat.PHP_EOL;
                echo "\$namedTimeFloat:".$namedTimeFloat.PHP_EOL;
                echo "\$sshdTimeFloat:".$sshdTimeFloat.PHP_EOL;

                }#if end

        #將本次http記錄覆寫到上次的記錄
        $params["info"]["preTimeFloat"]["http"]=$httpTimeFloat;

        #將本次https記錄覆寫到上次的記錄
        $params["info"]["preTimeFloat"]["https"]=$httpsTimeFloat;

        #將本次smtp記錄覆寫到上次的記錄
        $params["info"]["preTimeFloat"]["smtp"]=$smtpTimeFloat;

        #將本次imap記錄覆寫到上次的記錄
        $params["info"]["preTimeFloat"]["imap"]=$imapTimeFloat;

        #將本次named記錄覆寫到上次的記錄
        $params["info"]["preTimeFloat"]["named"]=$namedTimeFloat;

        #將本次sshd記錄覆寫到上次的記錄
        $params["info"]["preTimeFloat"]["sshd"]=$sshdTimeFloat;

        #初始化儲存暫時ip白名單的陣列
        $excludeIpsTmp=array();

        #針對每個暫時白名單ip
        foreach($params["info"]["excludeIpsTmp"] as $index=>$tmpIpInfo){

                #若暫存白名單已經過期
                if($tmpIpInfo["unixtime"]<time()-$params["info"]["tmp-white-ip-valid-time"]*3600){

                        #卸除之
                        unset($params["info"]["excludeIpsTmp"][$index]);

                        }#if end

                #反之
                else{

                        #變成 $excludeIpsTmp 的內容
                        $excludeIpsTmp[]=$params["info"]["excludeIpsTmp"][$index]["ip"];

                        }#else end

                }#foreach end

        #函式說明:
        #將多個多維陣列串聯起來,key從0開始排序.
        #回傳的結果:
        #$result["status"],"true"表執行正常,"false"代表執行不正常.
        #$result["error"],錯誤訊息陣列.
        #$result["function"],當前執行的函數.
        #$result["content"],合併好的一維陣列.
        #必填參數
        #$conf["inputArray"],陣列,要合併的一維陣列變數,例如:=array($array1,$array2);
        $conf["arrays::mergeMultiDimensionArray"]["inputArray"]=array($params["info"]["excludeIp"],$excludeIpsTmp);
        #可省略參數:
        #$conf["allowRepeat"],字串,預設為"false",不允許重複的結果;反之為"true".
        #$conf["allowRepeat"]="true";
        #$conf["equalKeyStruc"],字串陣列,若 allowRepeat 參數為 "false", 這該參數生效.該參數為用來判斷每個陣列的哪個鍵值路徑底下的數值相同時要進行取代,後者會取代前者.
        #$conf["equalKeyStruc"]=array();
        #參考資料:
        #無.
        #備註:
        #無.
        $mergeMultiDimensionArray=arrays::mergeMultiDimensionArray($conf["arrays::mergeMultiDimensionArray"]);
        unset($conf["arrays::mergeMultiDimensionArray"]);

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

                #設置執行失敗
                $result["status"]="false";

                #設置錯誤訊息
                $result["error"]=$mergeMultiDimensionArray;

                #回傳結果
                var_dump($result);

                #結束執行
                exit(1);

                }#if end

        #debug
        #var_dump(__LINE__,$mergeMultiDimensionArray);

        #涵式說明:
        #檢查 httpd 與 postfix/smtpd 的 log 與 named 的 log 與 sshd 的 log 把惡意連線的 IP 用防火牆阻擋
        #回傳結果:
        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息.
        #$result["function"],當前執行的函數名稱.
        #$result["argu"],所使用的參數.
        #$result["found"],是否有找到符合的檔案,"true"代表有;"false"代表沒有.
        #$result["content"],找到的檔案陣列.
        #必填參數:
        #$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
        $conf["cmd::blockAcctackIp"]["fileArgu"]=__FILE__;
        #可省略參數:
        #$conf["excludeIp"],字串陣列,白名單ip陣列.
        $conf["cmd::blockAcctackIp"]["excludeIp"]=$mergeMultiDimensionArray["content"];
        #$conf["logPath"],字串,httpd的log位置,預設為 "/var/log/httpd"
        #$conf["logPath"]="";
        #$conf["username"],字串,要用什麼使用者來執行,預設為root使用者
        #$conf["username"]="";
        #$conf["password"],字串,root使用者的密碼,
        #$conf["password"]="";
        #$conf["getIplistOnly"],字串,是否不阻擋IP只取得有問題的IP,預設為"false",要阻擋IP;"true"代表只取得有問題的IP.
        #$conf["getIplistOnly"]="true";
        $blockAcctackIp=cmd::blockAcctackIp($conf["cmd::blockAcctackIp"]);
        unset($conf["cmd::blockAcctackIp"]);

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

                #設置執行失敗
                $result["status"]="false";

                #設置錯誤訊息
                $result["error"]=$blockAcctackIp;

                #印出結果
                var_dump($result);

                #結束執行
                exit(1);

                }#if end

        #如果有執行封鎖IP的情形
        if(isset($blockAcctackIp["content"])){

                #comment
                echo "本次封鎖IP的結果如下:".PHP_EOL;
                var_dump($blockAcctackIp["content"]);
                var_dump($blockAcctackIp["reason"]);

                }#if end

        #睡一秒
        sleep(1);

        #結束執行
        return;

        }//function funcToRunWhenIdle end

?>