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~2026 MIN ZHI, CHENThis file is part of QBPWCF.QBPWCF is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.QBPWCF is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with QBPWCF. If not, see <http://www.gnu.org/licenses/>.*//*說明:註冊服務.範例:#註冊 每次執行 ps auxwf | cat 後,下一秒就刷新畫面重新執行 的服務registerService.php --cmd clear --cmds 'ps auxwf | cat' --cmds 'sleep 1'#註冊 執行 ssh 安全連線,並透過定期檢查 port 跟 指定指令 來確保服務在線 的服務registerService.php --cmd "ssh -i /home/liveuser/.ssh/id_ed25519 -N -L 5956:169.254.1.2:22 liveuser@domain" --name secure2liveuser@domain --keepServiceUp yes --checkCmd "echo 'env' | ssh liveuser@domain -p 5956 -i /home/liveuser/.ssh/id_ed25519" --runOnBoot yes --runNow yes --checkListenIp 127.0.0.1:5956/tcp備註:會被SELINUX預設設定阻擋*/#指派命名空間namespace qbpwcf;#取得 lib pathexec("php -f ".escapeshellarg(pathinfo(__FILE__)["dirname"]."/libexec/folderOfUsrLib.php"),$output,$status);#如果執行失敗if($status!==0){#debugvar_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){#debugvar_dump(__LINE__,$output);#結束執行,回傳shell 1.exit(1);}#if end#設置 include pathset_include_path($output[0].PATH_SEPARATOR.get_include_path());#匯入外部套件include("allInOne.php");#說明函式function help(){#印出指令說明echo "Usage of ".basename(__FILE__).":".PHP_EOL;echo "--cmd [command to run] 代表要執行的指令,若有多個則會按照順序執行.".PHP_EOL;echo "--name [servie name] 服務的名稱".PHP_EOL;echo "--runOnBoot [yes/no] 開機好就要啟動該服務,預設為yes.".PHP_EOL;echo "--runNow [yes/no] 馬上運行服務,預設為yes.".PHP_EOL;echo "--keepServiceUp [yes/no] 是否要加增確保該服務在線的設定,預設為no.".PHP_EOL;echo "--interval [秒數] 要多少時間就檢查一次服務是否在線.".PHP_EOL;echo "--checkListenIp [ipv4/ipv6]:[port]/[tcp/udp] 要檢查哪個ip位置的port與protocol有被使用,才代表服務有在線.".PHP_EOL;echo "\tip可用*代表所有網路界面取得的ip.".PHP_EOL;echo "--checkListenAddr [path to socket] 要檢查哪個路徑的unix domain socket有被使用,才代表服務有在線".PHP_EOL;echo "--checkCmd [command to check service] 用於確認服務是否有在線的指令,timeout為10秒.".PHP_EOL;echo "--runAfertService [run after specify service] 要於哪個服務啟動後執行".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";#$conf["parseFormVar"],解析表單變數(get\post),預設為"false"不使用;反之設置為"true".$conf["parseFormVar"]="false";#參考資料:#無.#備註:#僅能在命令列底下執行.#以後可將參數 --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;}#if end#檢查參數#函式說明:#檢查必填與可省略參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$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("cmd","name");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["mustBeFilledVariableType"]=array("array","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("backTime");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["skipableVariableName"]=array("runOnBoot","runNow","keepServiceUp","interval","checkListenIp","checkListenAddr","checkCmd","runAfertService");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["skipableVariableType"]=array("array","array","array","array","array","array","array","array");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["skipableVarDefaultValue"]=array(array("yes"),array("yes"),null,null,null,null,null,null);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["variableCheck::checkArguments"]["disallowAllSkipableVarIsEmpty"]="false";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$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"){#印出結果var_dump($checkArguments);#結束執行exit;}#if end#若檢查不通過if($checkArguments["passed"]==="false"){#提示用法help();#結束執行exit;}#if end#針對每個要執行的指令字串foreach($parseArgu["content"]["cmd"] as $index => $cmdStr){#解析成程式與參數#函式說明:#將指令字串解析成陣列,方便給予 external::callShell 使用#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],解析好的指令陣列.#$result["cmd"],解析好的指令名稱.#$result["argus"],解析好的參數陣列.#$result["argu"],所使用的參數.#必填參數#$conf["cmdStr"],字串,要解析的指令字串$conf["cmdStr"]=$cmdStr;#可省略參數:#無.#參考資料:#無.#備註:#無.$parseCmdString=cmd::parseCmdString($conf);unset($conf);#若執行失敗if($parseCmdString["status"]==="false"){#印出結果var_dump($parseCmdString);#結束執行exit;}#if end#取得要執行的程式$cmds[]=$parseCmdString["cmd"];#若存在程式對應的參數if(isset($parseCmdString["argus"])){#取得程式對應的參數$argus[]=$parseCmdString["argus"];}#if end#反之else{#設置無該程式的參數$argus[]=null;}#else end}#foreache end#取得要執行服務的指令#$cmds=;#取得目標參數$serviceName=$parseArgu["content"]["name"][0];#預設為 false$runOnBoot="false";#如果 runOnBoot 參數是 yesif($parseArgu["content"]["runOnBoot"][0]==="yes"){#轉換為 "true"$runOnBoot="true";}#if end#預設為 false$runNow="false";#如果 runNow參數 是 yesif($parseArgu["content"]["runNow"][0]==="yes"){#轉換為 "true"$runNow="true";}#if end#預設不用 cmd::keepServiceUp 來確保服務$keepServiceUp="false";#如果有指定 keepServiceUpif(isset($parseArgu["content"]["keepServiceUp"][0])){#如果參數 keepServiceUp 為 "true"if($parseArgu["content"]["keepServiceUp"][0]==="yes"){#設置 keepServiceUp 為 "true"$keepServiceUp="true";}#if end}#if end#如果有指定 intervalif(isset($parseArgu["content"]["interval"][0])){#設定interval$interval=$parseArgu["content"]["interval"][0];}#if end#初始化儲存判斷的方式$checkListen=array();#如果有指定 checkListenIpif(isset($parseArgu["content"]["checkListenIp"])){#針對每個 checkListenIpforeach($parseArgu["content"]["checkListenIp"] as $checkListenIp){#記錄要檢查的ip & port & protocol$checkListen[]=array("ip"=>$checkListenIp);}#foreach end}#if end#如果有指定 checkListenAddrif(isset($parseArgu["content"]["checkListenAddr"])){#針對每個 checkListenAddrforeach($parseArgu["content"]["checkListenAddr"] as $checkListenAddr){#記錄要檢查的 unix domain socket 路徑$checkListen[]=array("addr"=>$checkListenAddr);}#foreach end}#if end#如果有指定 checkCmdif(isset($parseArgu["content"]["checkCmd"])){#針對每個 checkCmdforeach($parseArgu["content"]["checkCmd"] as $checkCmd){#另外儲存成指定的格式$checkCmd=array("cmd"=>$checkCmd);#記錄用於檢查服務是否在線的指令$checkListen[]=array("cmd"=>$checkCmd);}#foreach end}#if end#如果有指定 runAfertServiceif(isset($parseArgu["content"]["runAfertService"])){#設置本服務要在哪些服務啟動後再啟動$unAfertService=$parseArgu["content"]["runAfertService"];}#if end#函式說明:#將要執行的程式變成透過 systemd 來運行.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息.#$result["function"],當前執行的函式名稱.#$result["argu"],所使用的參數.#$result["content"],執行的結果.#必填參數:#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑.$conf["fileArgu"]=__FILE__;#$conf["name"],字串,服務名稱,實際產生的system名稱會加上".service".$conf["name"]=$serviceName;#$conf["cmds"],字串陣列,每個要執行的程式.$conf["cmds"]=$cmds;#可省略參數:#$conf["params"],字串陣列,每個程式使用的參數.$conf["params"]=$argus;#$conf["enable"],字串,預設為"true",代表該服務為enable.$conf["enable"]=$runOnBoot;#$conf["startNow"],字串,預設為"true",代表該服務要立刻執行.$conf["startNow"]=$runNow;#如果存在 $keepServiceUpif(isset($keepServiceUp)){#$conf["keepServiceUp"],字串,是否要另外增加確保服務有保持啟動的服務,預設為"false"代表否;反之為"true"代表是.$conf["keepServiceUp"]=$keepServiceUp;}#if end#如果存在 $checkListenif(isset($checkListen)){#$conf["cmd::keepServiceUp"]["checkListen"],#$conf["checkListen"],陣列,用來判斷服務是否有正確啟動的條件,一個元素代表,其中要有一個socket info符合之,若元素的key為"ip",則其數值為[ipv4/ipv6]:port/protocol(tcp/udp);若元素的key為"addr",則其數值為unix domain socket 的位置與名稱;若元素的key為"name",則其數值為程序名稱;若元素的key為"cmd",則其數值為一陣列,該陣列的key有cmd,其value為要執行的指令,另外一個key為timeout,其value為秒數,預設為10秒,代表指令於10秒內結束為正常,反之為異常.$conf["checkListen"]=$checkListen;}#if end#如果存在 $intervalif(isset($interval)){#$conf["cmd::keepServiceUp"]["interval"],字串,檢查沒問題後,要多少秒後再檢查一次,預設為30秒,亦即"30".$conf["interval"]=$interval;}#if end#如果有設定 $unAfertServiceif(isset($unAfertService)){#$conf["runAfertService"],陣列,每個元素代表要在哪個服務啟動後再運行,預設不設定.$conf["runAfertService"]=$unAfertService;}#if end#參考資料:#無.#備註:#無.$registerService=cmd::registerService($conf);unset($conf);#如果執行失敗if($registerService["status"]==="false"){#debugvar_dump($registerService);#結束執行,回傳 shell 1exit(1);}#if end