From 1fb0d3185601ccd19198df7f0f6368b0ae046fb9 Mon Sep 17 00:00:00 2001 From: witersen <1801168257@qq.com> Date: Sat, 30 Apr 2022 20:04:20 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug=201=E3=80=81GetUserRepCon?= =?UTF-8?q?=E6=9C=89=E6=97=B6=E5=80=99=E4=BC=9A=E7=9B=B4=E6=8E=A5=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E8=80=8C=E4=B8=8D=E6=8F=90=E7=A4=BA=E6=97=A0=E6=9D=83?= =?UTF-8?q?=E9=99=902=E3=80=81=E9=80=9A=E8=BF=87=E9=87=8D=E5=AE=9A?= =?UTF-8?q?=E5=90=91stderr=E5=AE=9E=E7=8E=B0=E9=94=99=E8=AF=AF=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E4=BF=A1=E6=81=AF=E7=9A=84=E6=94=B6=E9=9B=863?= =?UTF-8?q?=E3=80=81=E5=A2=9E=E5=8A=A0=E7=94=A8=E6=88=B7=E6=89=AB=E6=8F=8F?= =?UTF-8?q?=E4=B8=AA=E4=BA=BA=E4=BB=93=E5=BA=93=E8=B7=AF=E5=BE=84=E6=9D=83?= =?UTF-8?q?=E9=99=90=E4=BF=A1=E6=81=AF=E5=88=97=E8=A1=A8=E6=97=B6=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E5=AD=98=E5=9C=A8=E6=80=A7=E6=A3=80=E6=9F=A5=20?= =?UTF-8?q?=E5=A6=82=E6=9E=9C=E4=B8=8D=E5=AD=98=E5=9C=A8=E5=88=99=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E4=BF=AE=E6=94=B9atuthz=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02.php/app/controller/statistics.class.php | 13 +- 02.php/app/controller/subversion.class.php | 5 +- 02.php/app/controller/svnrep.class.php | 94 +++++++++++++- 02.php/app/core/controller.class.php | 12 +- 02.php/app/function/file.function.php | 3 +- 02.php/app/function/socket.function.php | 6 +- .../SVNAdmin/src/class/SVNInfo.class.php | 5 +- .../SVNAdmin/src/class/SVNRep.class.php | 84 +++++++++---- 02.php/server/svnadmind.php | 119 ++++++++++-------- 9 files changed, 251 insertions(+), 90 deletions(-) diff --git a/02.php/app/controller/statistics.class.php b/02.php/app/controller/statistics.class.php index 3e9e8b8..4671130 100644 --- a/02.php/app/controller/statistics.class.php +++ b/02.php/app/controller/statistics.class.php @@ -3,7 +3,7 @@ * @Author: witersen * @Date: 2022-04-24 23:37:05 * @LastEditors: witersen - * @LastEditTime: 2022-04-28 01:53:50 + * @LastEditTime: 2022-04-30 19:22:53 * @Description: QQ:1801168257 */ @@ -40,6 +40,7 @@ class statistics extends controller * ----------负载计算开始---------- */ $laodavg = FunShellExec("cat /proc/loadavg | awk '{print $1,$2,$3}'"); + $laodavg = $laodavg['result']; $laodavgArray = explode(' ', $laodavg); //获取CPU15分钟前到现在的负载平均值 @@ -53,6 +54,7 @@ class statistics extends controller //获取cpu总核数 $cpuCount = FunShellExec('grep -c "model name" /proc/cpuinfo'); + $cpuCount = $cpuCount['result']; $cpuCount = (int)trim($cpuCount); //一分钟的平均负载 / (cpu总核数 * 2),超过100则为100 不超100为真实值取整 @@ -91,12 +93,14 @@ class statistics extends controller * st steal 实时 */ $topResult = FunShellExec('top -b -n 1 | grep Cpu'); + $topResult = $topResult['result']; preg_match('/ni,(.*?)id/', $topResult, $matches); $id = 100 - (float)trim($matches[1]); //cpu型号 $cpuModelArray = []; $cpuModelName = FunShellExec("cat /proc/cpuinfo | grep 'model name' | uniq"); + $cpuModelName = $cpuModelName['result']; $explodeArray = explode("\n", trim($cpuModelName)); foreach ($explodeArray as $value) { if (trim($value) != '') { @@ -107,10 +111,12 @@ class statistics extends controller //物理cpu个数 $cpuPhysical = FunShellExec("cat /proc/cpuinfo | grep 'physical id' | sort -u | wc -l"); + $cpuPhysical = $cpuPhysical['result']; $cpuPhysical = (int)trim($cpuPhysical); //每个物理cpu的物理核心数 $cpuPhysicalCore = FunShellExec("cat /proc/cpuinfo | grep 'cpu cores' | wc -l"); + $cpuPhysicalCore = $cpuPhysicalCore['result']; $cpuPhysicalCore = (int)trim($cpuPhysicalCore); //总物理核心数 = 物理cpu个数 * 每个物理cpu的物理核心数(每个物理cpu的物理核心数都一样吗?) @@ -118,6 +124,7 @@ class statistics extends controller //逻辑核心总数(线程总数) $cpuProcessor = FunShellExec("cat /proc/cpuinfo | grep 'processor' | wc -l"); + $cpuProcessor = $cpuProcessor['result']; $cpuProcessor = (int)trim($cpuProcessor); /** @@ -143,10 +150,12 @@ class statistics extends controller */ //物理内存总量 $memTotal = FunShellExec("cat /proc/meminfo | grep 'MemTotal' | awk '{print $2}'"); + $memTotal = $memTotal['result']; $memTotal = (int)trim($memTotal); //操作系统可用内存总量(没有使用空闲内存) $memFree = FunShellExec("cat /proc/meminfo | grep 'MemAvailable' | awk '{print $2}'"); + $memFree = $memFree['result']; $memFree = (int)trim($memFree); //操作系统已使用内存总量 @@ -177,6 +186,7 @@ class statistics extends controller function GetDisk() { $rs = FunShellExec('df -lh | grep -E "^(/)"'); + $rs = $rs['result']; //将多个连续的空格换为一个 $result = preg_replace("/\s{2,}/", ' ', $rs); @@ -220,6 +230,7 @@ class statistics extends controller { //操作系统类型和版本 $os = FunShellExec("cat /etc/redhat-release"); + $os = $os['result']; //仓库占用体积 $repSize = FunFormatSize(FunGetDirSizeDu(SVN_REPOSITORY_PATH)); diff --git a/02.php/app/controller/subversion.class.php b/02.php/app/controller/subversion.class.php index 9bcd7c4..f47507d 100644 --- a/02.php/app/controller/subversion.class.php +++ b/02.php/app/controller/subversion.class.php @@ -3,7 +3,7 @@ * @Author: witersen * @Date: 2022-04-24 23:37:05 * @LastEditors: witersen - * @LastEditTime: 2022-04-30 02:32:15 + * @LastEditTime: 2022-04-30 19:24:09 * @Description: QQ:1801168257 */ @@ -27,6 +27,7 @@ class subversion extends controller function GetStatus() { $result = FunShellExec("ps auxf | grep -v 'grep' | grep svnserve"); + $result = $result['result']; if ($result == '') { FunMessageExit(200, 0, 'svnserve服务未在运行,SVN用户将无法使用仓库浏览功能'); @@ -64,6 +65,7 @@ class subversion extends controller //检测运行信息 $runInfo = FunShellExec('ps auxf|grep -v "grep"|grep svnserve'); + $runInfo = $runInfo['result']; //检测安装信息 $installInfo = file_exists('/usr/bin/svnserve'); @@ -86,6 +88,7 @@ class subversion extends controller $version = '-'; if ($installed != 0) { $versionInfo = FunShellExec('svnserve --version'); + $versionInfo = $versionInfo['result']; preg_match_all(REG_SUBVERSION_VERSION, $versionInfo, $versionInfoPreg); if (array_key_exists(0, $versionInfoPreg[0])) { $version = trim($versionInfoPreg[1][0]); diff --git a/02.php/app/controller/svnrep.class.php b/02.php/app/controller/svnrep.class.php index d2c0d0c..df742d5 100644 --- a/02.php/app/controller/svnrep.class.php +++ b/02.php/app/controller/svnrep.class.php @@ -3,7 +3,7 @@ * @Author: witersen * @Date: 2022-04-24 23:37:05 * @LastEditors: witersen - * @LastEditTime: 2022-04-30 02:27:42 + * @LastEditTime: 2022-04-30 19:57:12 * @Description: QQ:1801168257 */ @@ -149,7 +149,69 @@ class svnrep extends controller } } - FunShellExec('echo \'' . $authzContet . '\' > ' . SVN_AUTHZ_FILE); + if ($authzContet != $this->globalAuthzContent) { + FunShellExec('echo \'' . $authzContet . '\' > ' . SVN_AUTHZ_FILE); + } + } + + /** + * 对用户有权限的仓库路径列表进行一一验证 + * + * 确保该仓库的路径存在于仓库的最新版本库中 + * + * 此方式可以清理掉因为目录/文件名进行修改/删除后造成的authz文件冗余 + * 但是此方式只能清理对此用户进行的有权限的授权 而不能清理无权限的情况 + * 以后有时间会考虑对所有的路径进行扫描和清理[todo] + */ + function SyncRepPathCheck() + { + //获取在authz文件配置的用户有权限的仓库路径列表 + $userRepList = []; + + //获取用户有权限的仓库列表 + $userRepList = array_merge($userRepList, $this->SVNAdminUser->GetUserPriRepListWithPriAndPath($this->globalAuthzContent, $this->globalUserName)); + + //获取用户所在的所有分组 + $userGroupList = $this->Svngorup->GetSvnUserAllGroupList($this->globalUserName); + + //获取分组有权限的仓库路径列表 + foreach ($userGroupList as $value) { + $userRepList = array_merge($userRepList, $this->SVNAdminGroup->GetGroupPriRepListWithPriAndPath($this->globalAuthzContent, $value)); + } + + //按照全路径去重 + $tempArray = []; + foreach ($userRepList as $key => $value) { + if (in_array($value['unique'], $tempArray)) { + unset($userRepList[$key]); + } else { + array_push($tempArray, $value['unique']); + } + } + + //处理不连续的下标 + $userRepList = array_values($userRepList); + + $authzContent = $this->globalAuthzContent; + + foreach ($userRepList as $key => $value) { + $cmd = sprintf("svnlook tree '%s' --full-paths --non-recursive '%s'", SVN_REPOSITORY_PATH . $value['repName'], $value['priPath']); + $result = FunShellExec($cmd); + + if (strstr($result['error'], 'svnlook: E160013:')) { + //路径在仓库不存在 + //从配置文件删除指定仓库的指定路径 + $tempResult = $this->SVNAdminRep->DelRepPath($authzContent, $value['repName'], $value['priPath']); + if ($tempResult != '1') { + $authzContent = $tempResult; + } + } + } + + //写入配置文件 + if ($authzContent != $this->globalAuthzContent) { + FunShellExec('echo \'' . $authzContent . '\' > ' . SVN_AUTHZ_FILE); + } } /** @@ -292,6 +354,23 @@ class svnrep extends controller */ $this->SyncRepAndAuthz(); + /** + * 及时更新 + */ + parent::UPdateAuthz(); + + /** + * 对用户有权限的仓库路径列表进行一一验证 + * + * 确保该仓库的路径存在于仓库的最新版本库中 + */ + $this->SyncRepPathCheck(); + + /** + * 及时更新 + */ + parent::UPdateAuthz(); + /** * 用户有权限的仓库路径列表 => svn_user_pri_paths数据表 * @@ -353,7 +432,7 @@ class svnrep extends controller 'rep_name' => $this->requestPayload['rep_name'] ]); - FunMessageExit(); + FunMessageExit(200, 1, '已保存'); } /** @@ -560,6 +639,7 @@ class svnrep extends controller //获取全路径的一层目录树 $cmdSvnlookTree = sprintf("svnlook tree '%s' --full-paths --non-recursive '%s'", SVN_REPOSITORY_PATH . $this->requestPayload['rep_name'], $path); $result = FunShellExec($cmdSvnlookTree); + $result = $result['result']; $resultArray = explode("\n", trim($result)); unset($resultArray[0]); $resultArray = array_values($resultArray); @@ -653,6 +733,7 @@ class svnrep extends controller //获取全路径的一层目录树 $cmdSvnlookTree = sprintf("svnlook tree '%s' --full-paths --non-recursive '%s'", SVN_REPOSITORY_PATH . $this->requestPayload['rep_name'], $path); $result = FunShellExec($cmdSvnlookTree); + $result = $result['result']; $resultArray = explode("\n", trim($result)); unset($resultArray[0]); $resultArray = array_values($resultArray); @@ -1209,10 +1290,10 @@ class svnrep extends controller //使用svndump $result = $this->SVNAdminRep->RepLoad($this->requestPayload['rep_name'], $this->requestPayload['fileName']); - if ($result == '') { + if ($result['error'] == '') { FunMessageExit(); } else { - FunMessageExit(200, 0, '导入错误', $result); + FunMessageExit(200, 0, '导入错误', $result['error']); } } @@ -1294,7 +1375,8 @@ class svnrep extends controller foreach ($file_arr as $file_item) { if ($file_item != '.' && $file_item != '..') { if (in_array($file_item, $hooks_file_list)) { - $hooks_type_list[$file_item]['shell'] = FunShellExec(sprintf("cat '%s'", SVN_REPOSITORY_PATH . $this->requestPayload['rep_name'] . '/' . 'hooks' . '/' . $file_item)); + $temp = FunShellExec(sprintf("cat '%s'", SVN_REPOSITORY_PATH . $this->requestPayload['rep_name'] . '/' . 'hooks' . '/' . $file_item)); + $hooks_type_list[$file_item]['shell'] = $temp['result']; $hooks_type_list[$file_item]['shell'] = trim($hooks_type_list[$file_item]['shell']); } } diff --git a/02.php/app/core/controller.class.php b/02.php/app/core/controller.class.php index 7eca346..0b019a3 100644 --- a/02.php/app/core/controller.class.php +++ b/02.php/app/core/controller.class.php @@ -3,7 +3,7 @@ * @Author: witersen * @Date: 2022-04-24 23:37:05 * @LastEditors: witersen - * @LastEditTime: 2022-04-28 02:03:15 + * @LastEditTime: 2022-04-30 19:44:21 * @Description: QQ:1801168257 */ @@ -150,4 +150,14 @@ class controller $arr = explode('.', $this->token); return $arr[1]; } + + /** + * 重新从authz文件中读取内容 + * + * 由于有些操作会更改authz文件内容且其它操作依赖这一实时结果 因此需要及时更新 + */ + final function UPdateAuthz() + { + $this->globalAuthzContent = file_exists(SVN_AUTHZ_FILE) ? file_get_contents(SVN_AUTHZ_FILE) : ''; + } } diff --git a/02.php/app/function/file.function.php b/02.php/app/function/file.function.php index d2d39b1..a30ed7d 100644 --- a/02.php/app/function/file.function.php +++ b/02.php/app/function/file.function.php @@ -3,7 +3,7 @@ * @Author: witersen * @Date: 2022-04-24 23:37:05 * @LastEditors: witersen - * @LastEditTime: 2022-04-26 16:58:42 + * @LastEditTime: 2022-04-30 19:26:32 * @Description: QQ:1801168257 */ @@ -63,6 +63,7 @@ function FunGetDirSizeDu($path) { $cmd = sprintf("du -s '%s' | awk '{print $1}'", $path); $result = FunShellExec($cmd); + $result = $result['result']; $result = (int)trim($result) * 1024; return $result; } diff --git a/02.php/app/function/socket.function.php b/02.php/app/function/socket.function.php index a28604d..6ebb230 100644 --- a/02.php/app/function/socket.function.php +++ b/02.php/app/function/socket.function.php @@ -3,7 +3,7 @@ * @Author: witersen * @Date: 2022-04-24 23:37:05 * @LastEditors: witersen - * @LastEditTime: 2022-04-30 02:14:02 + * @LastEditTime: 2022-04-30 19:17:16 * @Description: QQ:1801168257 */ @@ -21,7 +21,7 @@ function FunShellExec($shell) socket_write($socket, $shell); $reply = socket_read($socket, (int)SOCKET_READ_LENGTH); socket_close($socket); - return $reply = $reply == ISNULL ? '' : $reply; + return unserialize($reply); } /** @@ -34,12 +34,10 @@ function FunDetectState() { $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); - @socket_connect($sock, IPC_ADDRESS, (int)IPC_PORT); socket_set_nonblock($sock); - socket_set_block($sock); $v = array($sock); diff --git a/02.php/extension/SVNAdmin/src/class/SVNInfo.class.php b/02.php/extension/SVNAdmin/src/class/SVNInfo.class.php index 82c3729..a26be57 100644 --- a/02.php/extension/SVNAdmin/src/class/SVNInfo.class.php +++ b/02.php/extension/SVNAdmin/src/class/SVNInfo.class.php @@ -3,7 +3,7 @@ * @Author: witersen * @Date: 2022-04-27 17:58:13 * @LastEditors: witersen - * @LastEditTime: 2022-04-28 02:09:18 + * @LastEditTime: 2022-04-30 19:28:20 * @Description: QQ:1801168257 * @copyright: https://github.com/witersen/ */ @@ -34,6 +34,7 @@ class Info extends Core $bindHost = ''; $svnserveContent = FunShellExec('cat ' . $SVNSERVE_ENV_FILE); + $svnserveContent = $svnserveContent['result']; //匹配端口 if (preg_match('/--listen-port[\s]+([0-9]+)/', $svnserveContent, $portMatchs) != 0) { @@ -46,6 +47,7 @@ class Info extends Core } $listenContent = FunShellExec('cat ' . $LISTEN_FILE); + $listenContent = $listenContent['result']; if (!FunCheckJson($listenContent)) { //文件格式错误则初始化 @@ -73,6 +75,7 @@ class Info extends Core } $listenContent = FunShellExec('cat ' . $LISTEN_FILE); + $listenContent = $listenContent['result']; $listenArray = json_decode($listenContent, true); return [ diff --git a/02.php/extension/SVNAdmin/src/class/SVNRep.class.php b/02.php/extension/SVNAdmin/src/class/SVNRep.class.php index 0e8f5e5..f213ebc 100644 --- a/02.php/extension/SVNAdmin/src/class/SVNRep.class.php +++ b/02.php/extension/SVNAdmin/src/class/SVNRep.class.php @@ -3,7 +3,7 @@ * @Author: witersen * @Date: 2022-04-27 15:45:45 * @LastEditors: witersen - * @LastEditTime: 2022-04-30 02:26:16 + * @LastEditTime: 2022-04-30 19:56:44 * @Description: QQ:1801168257 * @copyright: https://github.com/witersen/ */ @@ -618,6 +618,29 @@ class Rep extends Core } } + /** + * 从配置文件删除指定仓库的指定路径 + * + * 1 已删除 + * string 正常 + */ + function DelRepPath($authzContent, $repName, $repPath) + { + //处理路径结尾 + if ($repPath != '/') { + if (substr($repPath, strlen($repPath) - 1, 1) == '/') { + $repPath = substr($repPath, 0, strlen($repPath) - 1); + } + } + + preg_match_all(sprintf($this->REG_AUTHZ_REP_SPECIAL_PATH_WITH_CON, $repName, str_replace('/', '\/', $repPath)), $authzContent, $authzContentPreg); + if (array_key_exists(0, $authzContentPreg[0])) { + return str_replace($authzContentPreg[0][0], "", $authzContent); + } else { + return '1'; + } + } + /** * 从配置文件删除指定仓库的所有路径 * @@ -866,6 +889,7 @@ class Rep extends Core $svnadminInfoCmd = sprintf("svnadmin info '%s'", $repPath); $cmdResult = FunShellExec($svnadminInfoCmd); + $cmdResult = $cmdResult['result']; preg_match_all($this->REG_REP_INFO, $cmdResult, $svnadminInfoPreg); @@ -884,6 +908,7 @@ class Rep extends Core $repPath = SVN_REPOSITORY_PATH . $repName; $svnadminInfoCmd = sprintf("svnlook tree '%s'", $repPath); $cmdResult = FunShellExec($svnadminInfoCmd); + $cmdResult = $cmdResult['result']; // $cmdResult = shell_exec($svnadminInfoCmd); $treeArray = explode("\n", $cmdResult); //去除数组中的空字符串键值 通常为最后一项 @@ -1186,7 +1211,8 @@ class Rep extends Core function GetRepRev($repName) { $cmd = sprintf("svnadmin info '%s' | grep 'Revisions' | awk '{print $2}'", SVN_REPOSITORY_PATH . $repName); - return (int)trim(FunShellExec($cmd)); + $result = FunShellExec($cmd); + return (int)$result['result']; } /** @@ -1195,7 +1221,8 @@ class Rep extends Core function GetRepDetail($repName) { $cmd = sprintf("svnadmin info '%s'", SVN_REPOSITORY_PATH . $repName); - return trim(FunShellExec($cmd)); + $result = FunShellExec($cmd); + return $result['result']; } /** @@ -1208,7 +1235,8 @@ class Rep extends Core function GetRepRevFileSize($repName, $filePath) { $cmd = sprintf("svnlook filesize '%s' '%s'", SVN_REPOSITORY_PATH . $repName, $filePath); - $size = (int)trim(FunShellExec($cmd)); + $result = FunShellExec($cmd); + $size = (int)$result['result']; return FunFormatSize($size); } @@ -1219,6 +1247,7 @@ class Rep extends Core { $cmd = sprintf("svnlook history --limit 1 '%s' '%s'", SVN_REPOSITORY_PATH . $repName, $filePath); $result = FunShellExec($cmd); + $result = $result['result']; $resultArray = explode("\n", $result); $content = preg_replace("/\s{2,}/", ' ', $resultArray[2]); $contentArray = explode(' ', $content); @@ -1232,7 +1261,7 @@ class Rep extends Core { $cmd = sprintf("svnlook author -r %s '%s'", $rev, SVN_REPOSITORY_PATH . $repName); $result = FunShellExec($cmd); - return $result; + return $result['result']; } /** @@ -1242,7 +1271,7 @@ class Rep extends Core { $cmd = sprintf("svnlook date -r %s '%s'", $rev, SVN_REPOSITORY_PATH . $repName); $result = FunShellExec($cmd); - return $result; + return $result['result']; } /** @@ -1252,7 +1281,7 @@ class Rep extends Core { $cmd = sprintf("svnlook log -r %s '%s'", $rev, SVN_REPOSITORY_PATH . $repName); $result = FunShellExec($cmd); - return $result; + return $result['result']; } /** @@ -1292,22 +1321,31 @@ class Rep extends Core { $cmd = sprintf("svn list '%s' --username '%s' --password '%s' --no-auth-cache --non-interactive --trust-server-cert", $checkoutHost . '/' . $repName . $repPath, $svnUserName, $svnUserPass); $result = FunShellExec($cmd); - if (strstr($result, 'svn: E170001: Authentication error from server: Password incorrect')) { - FunMessageExit(200, 0, '密码错误'); - } - if (strstr($result, 'svn: E170001: Authorization failed')) { - FunMessageExit(200, 0, '无访问权限'); - } - if (strstr($result, 'svn: E220003: Invalid authz configuration')) { - FunMessageExit(200, 0, '配置文件配置错误 请使用svnauthz-validate工具检查'); - } - if (strstr($result, 'svn: E170013: Unable to connect to a repository at URL')) { - FunMessageExit(200, 0, '其它错误' . $result); - } - if (strstr($result, 'svn: warning: W160013:') || strstr($result, "svn: E200009: Could not list all targets because some targets don't exist")) { - // FunMessageExit(200, 0, '该路径在仓库不存在 请刷新以同步'); - FunMessageExit(200, 0, '该路径在仓库已不在版本库中'); + + if ($result['resultCode'] != 0) { + //: Authentication error from server: Password incorrect + if (strstr($result['error'], 'svn: E170001')) { + FunMessageExit(200, 0, '密码错误'); + } + //: Authorization failed + if (strstr($result['error'], 'svn: E170001')) { + FunMessageExit(200, 0, '无访问权限'); + } + //: Invalid authz configuration + if (strstr($result['error'], 'svn: E220003')) { + FunMessageExit(200, 0, '配置文件配置错误 请使用svnauthz-validate工具检查'); + } + //: Unable to connect to a repository at URL + if (strstr($result['error'], 'svn: E170013')) { + FunMessageExit(200, 0, '无法连接到仓库'); + } + //: Could not list all targets because some targets don't exist + if (strstr($result['error'], 'svn: warning: W160013') || strstr($result['error'], "svn: E200009")) { + FunMessageExit(200, 0, '该授权路径在仓库不存在 请刷新以同步'); + } + FunMessageExit(200, 0, '其它错误' . $result['error']); } - return $result; + + return $result['result']; } } diff --git a/02.php/server/svnadmind.php b/02.php/server/svnadmind.php index e153492..eb5eb2e 100644 --- a/02.php/server/svnadmind.php +++ b/02.php/server/svnadmind.php @@ -3,7 +3,7 @@ * @Author: witersen * @Date: 2022-04-24 23:37:06 * @LastEditors: witersen - * @LastEditTime: 2022-04-28 02:22:01 + * @LastEditTime: 2022-04-30 19:59:26 * @Description: QQ:1801168257 */ @@ -34,7 +34,7 @@ class Daemon /** * 将程序变为守护进程 */ - private function initDaemon() + private function InitDeamon() { $pid = pcntl_fork(); if ($pid < 0) { @@ -64,13 +64,13 @@ class Daemon fclose(STDERR); } file_put_contents($this->pidFile, getmypid()); - $this->initSocket(); + $this->InitSocket(); } /** - * 监听指定端口 + * 创建TCP套接字并监听指定端口 */ - private function initSocket() + private function InitSocket() { //创建套接字 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or exit('启动失败:socket_create 错误' . PHP_EOL); @@ -97,53 +97,65 @@ class Daemon if ($pid == -1) { exit('启动失败:pcntl_fork 错误' . PHP_EOL); } else if ($pid == 0) { - $this->handleRequest($client); + $this->HandleRequest($client); } else { } } } /** - * socket程序接收和处理请求 + * 接收TCP连接并处理指令 */ - private function handleRequest($client) + private function HandleRequest($client) { //接收客户端发送的数据 - $data = socket_read($client, SOCKET_READ_LENGTH); - - //console - $this->workMode == 'console' ? print_r(PHP_EOL . '---------receive---------' . PHP_EOL . $data . PHP_EOL) : ''; - - if (trim($data) != '') { - /** - * shell_exec方法拿不到执行指令的错误抛出信息 - */ - // $result = shell_exec($data); - - /** - * passthru会将所有的结果(包括正确的和错误的抛出信息输出) - * 可以使用 ob_start ob_get_contents ob_end_clean 拿到缓冲区的内容 - * - * 此方法在console调试模式下会导致 $result 变量拿不到值; - * 但是在daemon模式下 $result 变量可以拿到值(猜测是输入到终端与输出到缓冲区的影响) - */ + $cmmand = socket_read($client, SOCKET_READ_LENGTH); + + //console模式 + if ($this->workMode == 'console') { + echo PHP_EOL . '---------receive---------' . PHP_EOL; + echo $cmmand . PHP_EOL; + } + + if (trim($cmmand) != '') { + //定义错误输出文件路径 + $stderrFile = TEMP_PATH . uniqid(); + + //将标准错误重定向到文件 + //使用状态码来标识错误信息 ob_start(); - passthru($data); - $result = ob_get_contents(); + passthru($cmmand . " 2>$stderrFile", $resultCode); + $buffer = ob_get_contents(); ob_end_clean(); + + //将错误信息和正确信息分类收集 + $result = [ + 'resultCode' => $resultCode, + 'result' => trim($buffer), + 'error' => file_get_contents($stderrFile) + ]; + + //销毁文件 + unlink($stderrFile); } else { //探测程序会发送空信息 - $result = ''; + $result = [ + 'resultCode' => 0, + 'result' => '', + 'error' => '' + ]; } - //console - $this->workMode == 'console' ? print_r(PHP_EOL . '---------result---------' . PHP_EOL . $result . PHP_EOL) : ''; - - //处理没有返回内容的情况 否则 socket_write 遇到空内容会报错 - $result = trim($result) == '' ? ISNULL : trim($result); + //console模式 + if ($this->workMode == 'console') { + echo PHP_EOL . '---------result---------' . PHP_EOL; + echo 'resultCode: ' . $result['resultCode'] . PHP_EOL; + echo 'result: ' . $result['result'] . PHP_EOL; + echo 'error: ' . $result['error'] . PHP_EOL; + } - //将结果返回给客户端 - socket_write($client, $result, strlen($result)) or die('启动失败:socket_write 错误' . PHP_EOL); + //将结果序列化并返回 + socket_write($client, serialize($result), strlen(serialize($result))) or die('失败:socket_write 错误' . PHP_EOL); //关闭会话 socket_close($client); @@ -155,7 +167,7 @@ class Daemon /** * 检查操作系统是否符合要求 */ - private function checkSysType() + private function CheckSysType() { if (PHP_OS != 'Linux') { exit('启动失败:当前操作系统不为Linux' . PHP_EOL); @@ -173,7 +185,7 @@ class Daemon /** * 检查php版本是否符合要求 */ - private function checkPhpVersion() + private function CheckPhpVersion() { if (PHP_VERSION < Required_PHP_VERSION) { exit('启动失败:当前的PHP版本为:' . PHP_VERSION . ',要求的最低PHP版本为:' . Required_PHP_VERSION . PHP_EOL); @@ -183,7 +195,7 @@ class Daemon /** * 检查需要的函数是否被禁用 */ - private function checkDisabledFunction() + private function CheckDisabledFunction() { $disabled_function = explode(',', ini_get('disable_functions')); $cli_needed_function = unserialize(CLI_NEEDED_FUNCTION); @@ -200,7 +212,7 @@ class Daemon /** * 以守护进程模式工作 */ - private function startDaemon() + private function StartDaemon() { if (file_exists($this->pidFile)) { $pid = file_get_contents($this->pidFile); @@ -209,13 +221,13 @@ class Daemon exit('程序正在运行中' . PHP_EOL); } } - $this->initDaemon(); + $this->InitDeamon(); } /** * 关闭守护进程 */ - private function stopDaemon() + private function StopDaemon() { if (file_exists($this->pidFile)) { $pid = file_get_contents($this->pidFile); @@ -227,27 +239,27 @@ class Daemon /** * 以控制台模式工作 用于调试 */ - private function startConsole() + private function StartConsole() { - $this->initSocket(); + $this->InitSocket(); } - public function run($argv) + public function Run($argv) { - $this->checkSysType(); - $this->checkPhpVersion(); - $this->checkDisabledFunction(); + $this->CheckSysType(); + $this->CheckPhpVersion(); + $this->CheckDisabledFunction(); if (isset($argv[1])) { $this->workMode = $argv[1]; if (!in_array($this->workMode, $this->scripts)) { exit('用法:php svnadmin.php [start | stop | console]' . PHP_EOL); } if ($this->workMode == 'start') { - $this->startDaemon(); + $this->StartDaemon(); } else if ($this->workMode == 'stop') { - $this->stopDaemon(); + $this->StopDaemon(); } else if ($this->workMode == 'console') { - $this->startConsole(); + $this->StartConsole(); } } else { exit('用法:php svnadmin.php [start | stop | console]' . PHP_EOL); @@ -255,7 +267,10 @@ class Daemon } } +/** + * 将工作模式限制在cli模式 + */ if (preg_match('/cli/i', php_sapi_name())) { $deamon = new Daemon(); - $deamon->run($argv); + $deamon->Run($argv); }