提交 a5909acd authored 作者: 陈泽健's avatar 陈泽健

docs(service-inspection): 更新服务自检文档中的配置文件与日志导出规范

- 更新了PRD需求文档中的日志文件导出规则,支持最近三天历史日志
- 修改了配置文件导出范围,仅包含.yml、.properties、.json、.js、.xml格式文件
- 优化了Python服务日志文件的导出规则,支持历史日志备份文件
- 在计划执行文档中更新了服务导出配置的具体实现方式
- 添加了配置文件扩展名过滤和日志时间过滤的功能说明
- 重构了导出逻辑的文件处理方式,支持字符串和哈希表两种格式
- 移除了中间件日志导出的独立功能模块
- 增强了Redis和MySQL检测的详细指标展示功能
- 优化了检测报告的格式化输出,改进了详情信息的显示方式
- 调整了检测总结部分的位置布局
上级 af1554d7
...@@ -2534,11 +2534,6 @@ function Main { ...@@ -2534,11 +2534,6 @@ function Main {
$middlewareTrackerLogPath = "/var/fdfs/tracker/logs" $middlewareTrackerLogPath = "/var/fdfs/tracker/logs"
} }
# 创建中间件日志导出目录
$createDirCmd = "mkdir -p ./middleware_logs/{mqtt,redis,mysql,fdfs/storage,fdfs/tracker} 2>/dev/null || true"
Invoke-SSHCommand -HostName $server.IP -User $server.User -Pass $server.Pass -Port $server.Port -Command $createDirCmd | Out-Null
Write-Log -Level "INFO" -Message "[中间件] 日志导出目录: ./middleware_logs"
# 中间件连接检测(支持双模式) # 中间件连接检测(支持双模式)
if ($global:UseShellMode) { if ($global:UseShellMode) {
$middlewareResults = Test-MQTTConnection-Shell -Server $server $middlewareResults = Test-MQTTConnection-Shell -Server $server
...@@ -2562,80 +2557,6 @@ function Main { ...@@ -2562,80 +2557,6 @@ function Main {
Write-Log -Level "INFO" -Message "========== 中间件连接检测完成 ==========" Write-Log -Level "INFO" -Message "========== 中间件连接检测完成 =========="
# ------------------------------
# 中间件日志下载到本地(PRD 4.18 日志导出功能)
# ------------------------------
Write-Host ""
Write-Log -Level "INFO" -Message "========== 开始下载中间件日志到本地 =========="
# 检查 pscp.exe 是否可用
if (-not $global:PSCP_PATH -or -not (Test-Path $global:PSCP_PATH)) {
Write-Log -Level "WARN" -Message "[中间件] pscp.exe 未找到,跳过中间件日志下载"
Write-Log -Level "INFO" -Message " 请将 pscp.exe 放在脚本同目录下以启用日志下载功能"
Write-Log -Level "INFO" -Message " 下载地址: https://the.earth.li/~sgtatham/putty/latest/w64/pscp.exe"
} else {
# 创建本地日志目录
$localMiddlewareLogDir = Join-Path $SCRIPT_DIR "middleware_logs"
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$localLogDirWithTimestamp = "${localMiddlewareLogDir}_$($server.IP)_$timestamp"
try {
# 检查远程服务器上是否有中间件日志
$checkLogCmd = "test -d ./middleware_logs && echo 'EXISTS' || echo 'NOT_FOUND'"
$logCheckResult = Invoke-SSHCommand -HostName $server.IP -User $server.User -Pass $server.Pass -Port $server.Port -Command $checkLogCmd
$logExists = ($logCheckResult.Output -join "").Trim()
if ($logExists -eq "EXISTS") {
Write-Log -Level "INFO" -Message "[中间件] 发现远程日志目录,开始下载到本地: $localLogDirWithTimestamp"
# 使用 pscp 下载整个 middleware_logs 目录
# 注意:pscp 递归复制需要 -r 参数,且远程目录路径需要以 / 结尾
$remoteLogPath = "./middleware_logs/"
$pscpArgs = @(
"-batch",
"-r", # 递归复制目录(需要在 -scp 之前)
"-scp",
"-P", "$($server.Port)",
"-pw", "$($server.Pass)",
"$($server.User)@$($server.IP):$remoteLogPath",
"$localLogDirWithTimestamp"
)
Write-Log -Level "INFO" -Message "[中间件] 执行 pscp 下载命令..."
$pscpOutput = & $global:PSCP_PATH @pscpArgs 2>&1
$pscpExitCode = $LASTEXITCODE
if ($pscpExitCode -eq 0 -and (Test-Path $localLogDirWithTimestamp)) {
Write-Log -Level "SUCCESS" -Message "[中间件] 中间件日志下载成功: $localLogDirWithTimestamp"
# 统计下载的日志文件
$logFiles = Get-ChildItem -Path $localLogDirWithTimestamp -Recurse -File -ErrorAction SilentlyContinue
if ($logFiles) {
Write-Log -Level "INFO" -Message "[中间件] 下载的日志文件数量: $($logFiles.Count)"
$totalSize = ($logFiles | Measure-Object -Property Length -Sum).Sum
Write-Log -Level "INFO" -Message "[中间件] 下载的日志总大小: $([math]::Round($totalSize / 1MB, 2)) MB"
}
} else {
Write-Log -Level "WARN" -Message "[中间件] 中间件日志下载失败 (退出码: $pscpExitCode)"
if ($pscpOutput) {
Write-Log -Level "INFO" -Message "[中间件] pscp 输出: $pscpOutput"
}
}
# 清理远程服务器上的临时日志目录(可选)
$cleanupCmd = "rm -rf ./middleware_logs 2>/dev/null && echo 'CLEANED' || echo 'SKIP'"
$cleanupResult = Invoke-SSHCommand -HostName $server.IP -User $server.User -Pass $server.Pass -Port $server.Port -Command $cleanupCmd
Write-Log -Level "INFO" -Message "[中间件] 远程临时日志目录已清理"
} else {
Write-Log -Level "INFO" -Message "[中间件] 远程服务器上未发现中间件日志目录,跳过下载"
}
} catch {
Write-Log -Level "ERROR" -Message "[中间件] 日志下载过程中发生异常: $($_.Exception.Message)"
}
}
Write-Log -Level "INFO" -Message "========== 中间件日志下载完成 =========="
# 检测配置文件中的IP地址 # 检测配置文件中的IP地址
Write-Host "" Write-Host ""
Write-Log -Level "INFO" -Message "========== 开始检测配置文件 IP ==========" Write-Log -Level "INFO" -Message "========== 开始检测配置文件 IP =========="
......
...@@ -46,13 +46,13 @@ $script:NewPlatformBackend = @( ...@@ -46,13 +46,13 @@ $script:NewPlatformBackend = @(
@{ Name = "auth-sso-auth"; BaseDir = "/data/services/api/auth/auth-sso-auth"; Files = @("log.out"; "config") } @{ Name = "auth-sso-auth"; BaseDir = "/data/services/api/auth/auth-sso-auth"; Files = @("log.out"; "config") }
@{ Name = "auth-sso-gatway"; BaseDir = "/data/services/api/auth/auth-sso-gatway"; Files = @("log.out"; "config") } @{ Name = "auth-sso-gatway"; BaseDir = "/data/services/api/auth/auth-sso-gatway"; Files = @("log.out"; "config") }
@{ Name = "auth-sso-system"; BaseDir = "/data/services/api/auth/auth-sso-system"; Files = @("log.out"; "config") } @{ Name = "auth-sso-system"; BaseDir = "/data/services/api/auth/auth-sso-system"; Files = @("log.out"; "config") }
@{ Name = "java-meeting2.0"; BaseDir = "/data/services/api/java-meeting/java-meeting2.0"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; "config") } @{ Name = "java-meeting2.0"; BaseDir = "/data/services/api/java-meeting/java-meeting2.0"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; @{ Path="logs/timeFile"; Type="mtime"; Days=3 }; @{ Path="config"; Type="ext-filter"; Extensions=@("*.yml","*.properties","*.json","*.js","*.xml") }) }
@{ Name = "java-meeting-extapi"; BaseDir = "/data/services/api/java-meeting/java-meeting-extapi"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; "config") } @{ Name = "java-meeting-extapi"; BaseDir = "/data/services/api/java-meeting/java-meeting-extapi"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; @{ Path="logs/timeFile"; Type="mtime"; Days=3 }; @{ Path="config"; Type="ext-filter"; Extensions=@("*.yml","*.properties","*.json","*.js","*.xml") }) }
@{ Name = "java-message-scheduling"; BaseDir = "/data/services/api/java-meeting/java-message-scheduling"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; "config") } @{ Name = "java-message-scheduling"; BaseDir = "/data/services/api/java-meeting/java-message-scheduling"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; @{ Path="logs/timeFile"; Type="mtime"; Days=3 }; @{ Path="config"; Type="ext-filter"; Extensions=@("*.yml","*.properties","*.json","*.js","*.xml") }) }
@{ Name = "java-mqtt"; BaseDir = "/data/services/api/java-meeting/java-mqtt"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; "config") } @{ Name = "java-mqtt"; BaseDir = "/data/services/api/java-meeting/java-mqtt"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; @{ Path="logs/timeFile"; Type="mtime"; Days=3 }; @{ Path="config"; Type="ext-filter"; Extensions=@("*.yml","*.properties","*.json","*.js","*.xml") }) }
@{ Name = "java-quartz"; BaseDir = "/data/services/api/java-meeting/java-quartz"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; "config") } @{ Name = "java-quartz"; BaseDir = "/data/services/api/java-meeting/java-quartz"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; @{ Path="logs/timeFile"; Type="mtime"; Days=3 }; @{ Path="config"; Type="ext-filter"; Extensions=@("*.yml","*.properties","*.json","*.js","*.xml") }) }
@{ Name = "python-cmdb"; BaseDir = "/data/services/api/python-cmdb"; Files = @("log/uinfo.log"; "log/error.log"; "log/uwsgi.log"; "setting.conf"; "cmdb/bus/config/settingbus.conf") } @{ Name = "python-cmdb"; BaseDir = "/data/services/api/python-cmdb"; Files = @(@{ Path="log"; Type="ext-filter"; Extensions=@("*.log", "*.log.1", "*.log.2", "*.log.3") }; "setting.conf"; "cmdb/bus/config/settingbus.conf") }
@{ Name = "python-voice"; BaseDir = "/data/services/api/python-voice"; Files = @("log/uinfo.log"; "log/uwsgi.log"; "setting.conf"; "uvoice/bus/config/settingbus.conf") } @{ Name = "python-voice"; BaseDir = "/data/services/api/python-voice"; Files = @(@{ Path="log"; Type="ext-filter"; Extensions=@("*.log", "*.log.1", "*.log.2", "*.log.3") }; "setting.conf"; "uvoice/bus/config/settingbus.conf") }
) )
$script:NewPlatformMiddleware = @( $script:NewPlatformMiddleware = @(
...@@ -78,8 +78,8 @@ $script:OldPlatformFrontend = @( ...@@ -78,8 +78,8 @@ $script:OldPlatformFrontend = @(
) )
$script:OldPlatformBackend = @( $script:OldPlatformBackend = @(
@{ Name = "api-java-meeting2.0"; BaseDir = "/var/www/java/api-java-meeting2.0"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; "config") } @{ Name = "api-java-meeting2.0"; BaseDir = "/var/www/java/api-java-meeting2.0"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; @{ Path="logs/timeFile"; Type="mtime"; Days=3 }; @{ Path="config"; Type="ext-filter"; Extensions=@("*.yml","*.properties","*.json","*.js","*.xml") }) }
@{ Name = "external-meeting-api"; BaseDir = "/var/www/java/external-meeting-api"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; "config") } @{ Name = "external-meeting-api"; BaseDir = "/var/www/java/external-meeting-api"; Files = @("logs/ubains-INFO-AND-ERROR.log"; "logs/ubains-ERROR.log"; @{ Path="logs/timeFile"; Type="mtime"; Days=3 }; @{ Path="config"; Type="ext-filter"; Extensions=@("*.yml","*.properties","*.json","*.js","*.xml") }) }
@{ Name = "html-ops"; BaseDir = "/var/www/html"; Files = @("setting.conf"; "log/uinfo.log"; "log/error.log"; "log/uwsgi.log") } @{ Name = "html-ops"; BaseDir = "/var/www/html"; Files = @("setting.conf"; "log/uinfo.log"; "log/error.log"; "log/uwsgi.log") }
) )
...@@ -189,27 +189,62 @@ function Export-ConfigAndLogs { ...@@ -189,27 +189,62 @@ function Export-ConfigAndLogs {
$copyErrors = @() $copyErrors = @()
foreach ($fileItem in $svcFiles) { foreach ($fileItem in $svcFiles) {
$srcPath = "$svcBase/$fileItem"
$dstPath = $svcTmpDir $dstPath = $svcTmpDir
# Build remote copy command based on file type # 判断文件规范类型:字符串 or 哈希表(ext-filter / mtime)
if ($fileItem -is [hashtable]) {
# ---- 哈希表格式:支持 ext-filter(扩展名过滤)和 mtime(时间过滤)----
$itemType = $fileItem.Type
$itemPath = $fileItem.Path
$srcPath = "$svcBase/$itemPath"
if ($itemType -eq "ext-filter") {
# config 目录扩展名过滤:仅复制指定扩展名的文件
$exts = $fileItem.Extensions
$findNames = ($exts | ForEach-Object { "-name '$_'" }) -join " -o "
$copyCmd = "if [ -d `"$srcPath`" ]; then mkdir -p `"$dstPath/$itemPath`" && (cd `"$svcBase`" && find `"$itemPath`" -type f \( $findNames \) 2>/dev/null | while IFS= read -r f; do mkdir -p `"$dstPath/`$(dirname `"`${f}`")`" && cp `"`${f}`" `"$dstPath/`${f}`" 2>/dev/null; done); fi; echo EXIT:`$?"
}
elseif ($itemType -eq "mtime") {
# 目录时间过滤:仅复制最近 N 天的文件(用于 timeFile 和 Python log 目录)
$days = $fileItem.Days
# 诊断+复制:先统计源文件数量,再执行按时间过滤复制
$copyCmd = "echo DIAG_LS=`$(ls `"$srcPath`" 2>/dev/null | wc -l) DIAG_MTIME=`$(find `"$srcPath`" -type f -mtime -$days 2>/dev/null | wc -l); if [ -d `"$srcPath`" ]; then mkdir -p `"$dstPath/$itemPath`" && find `"$srcPath`" -type f -mtime -$days -exec cp {} `"$dstPath/$itemPath/`" \; 2>/dev/null; fi; echo EXIT:`$?"
}
else {
# 未知类型,跳过
$copyErrors += "$itemPath (unknown type: $itemType)"
continue
}
$itemLabel = if ($itemType -eq "ext-filter") { "$itemPath (ext-filter)" } else { "$itemPath (mtime ${days}d)" }
}
else {
# ---- 字符串格式:原有的单文件/目录/通配符逻辑 ----
$srcPath = "$svcBase/$fileItem"
$itemLabel = $fileItem
if ($fileItem -match '\*') { if ($fileItem -match '\*') {
# Wildcard pattern # 通配符模式
$copyCmd = "cp -r ${srcPath} ${dstPath}/ 2>/dev/null; echo EXIT:$?" $copyCmd = "cp -r ${srcPath} ${dstPath}/ 2>/dev/null; echo EXIT:`$?"
} }
else { else {
# Check if file or dir, copy accordingly # 检查文件或目录,对应复制
$copyCmd = 'if [ -d "' + $srcPath + '" ]; then cp -r "' + $srcPath + '" "' + $dstPath + '/" 2>/dev/null; elif [ -f "' + $srcPath + '" ]; then mkdir -p "$(dirname "' + $dstPath + '/' + $fileItem + '")"; cp "' + $srcPath + '" "' + $dstPath + '/' + $fileItem + '" 2>/dev/null; fi; echo EXIT:$?' $copyCmd = 'if [ -d "' + $srcPath + '" ]; then cp -r "' + $srcPath + '" "' + $dstPath + '/" 2>/dev/null; elif [ -f "' + $srcPath + '" ]; then mkdir -p "$(dirname "' + $dstPath + '/' + $fileItem + '")"; cp "' + $srcPath + '" "' + $dstPath + '/' + $fileItem + '" 2>/dev/null; fi; echo EXIT:$?'
} }
}
$copyResult = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $copyCmd $copyResult = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $copyCmd
$copyOutput = ($copyResult.Output | Out-String).Trim() $copyOutput = ($copyResult.Output | Out-String).Trim()
# 调试日志:输出发送的命令和远程响应
Write-Log -Level "INFO" -Message " [CMD] $itemLabel => $copyCmd"
Write-Log -Level "INFO" -Message " [RES] $itemLabel <= $($copyOutput.Substring(0, [Math]::Min(500, $copyOutput.Length)))"
if ($copyOutput -match 'EXIT:0') { if ($copyOutput -match 'EXIT:0') {
$copiedFiles += $fileItem $copiedFiles += $itemLabel
} }
else { else {
$copyErrors += $fileItem $copyErrors += $itemLabel
} }
} }
......
...@@ -555,6 +555,40 @@ test -f "/root/#{SCRIPT_NAME}" && echo "/root/#{SCRIPT_NAME}" || echo NOT_FOUND ...@@ -555,6 +555,40 @@ test -f "/root/#{SCRIPT_NAME}" && echo "/root/#{SCRIPT_NAME}" || echo NOT_FOUND
$redisClients = $matches[1] $redisClients = $matches[1]
} }
# 获取运行天数
$redisUptime = ""
if ($outputText -match 'uptime_in_days\s*:\s*(\d+)') {
$redisUptime = $matches[1]
}
# 获取每秒操作数
$redisOps = ""
if ($outputText -match 'instantaneous_ops_per_sec\s*:\s*(\d+)') {
$redisOps = $matches[1]
}
# 获取数据库键数
$redisKeys = ""
if ($outputText -match 'db0:keys=(\d+)') {
$redisKeys = $matches[1]
}
# 获取AOF持久化状态
$redisAof = ""
if ($outputText -match 'aof_enabled\s*:\s*(\d+)') {
$redisAof = if ($matches[1] -eq '1') { "已启用" } else { "未启用" }
}
# 获取容器CPU和内存使用
$redisCpuUsage = ""
$redisMemUsage = ""
if ($outputText -match 'CPU使用:\s*([\d.]+%)') {
$redisCpuUsage = $matches[1]
}
if ($outputText -match '内存使用:\s*([\d.]+\s*\w+)') {
$redisMemUsage = $matches[1]
}
if ($isConnected) { if ($isConnected) {
if ($outputText -match '所有核心测试通过') { if ($outputText -match '所有核心测试通过') {
$detailMsg = "Redis服务完全正常(连接+读写+删除+信息采集)" $detailMsg = "Redis服务完全正常(连接+读写+删除+信息采集)"
...@@ -588,8 +622,14 @@ test -f "/root/#{SCRIPT_NAME}" && echo "/root/#{SCRIPT_NAME}" || echo NOT_FOUND ...@@ -588,8 +622,14 @@ test -f "/root/#{SCRIPT_NAME}" && echo "/root/#{SCRIPT_NAME}" || echo NOT_FOUND
if ($isConnected) { if ($isConnected) {
$detailInfo += " | 容器: $detectedContainer | 端口: $detectedPort" $detailInfo += " | 容器: $detectedContainer | 端口: $detectedPort"
if ($redisVersion) { $detailInfo += " | 版本: $redisVersion" } if ($redisVersion) { $detailInfo += " | 版本: $redisVersion" }
if ($redisMemory) { $detailInfo += " | 内存: $redisMemory" } if ($redisUptime) { $detailInfo += " | 运行天数: $redisUptime" }
if ($redisClients) { $detailInfo += " | 连接数: $redisClients" } if ($redisMemory) { $detailInfo += " | 内存使用: $redisMemory" }
if ($redisClients) { $detailInfo += " | 当前连接数: $redisClients" }
if ($redisOps) { $detailInfo += " | 每秒操作数: $redisOps" }
if ($redisKeys) { $detailInfo += " | 数据库键数: $redisKeys" }
if ($redisAof) { $detailInfo += " | AOF持久化: $redisAof" }
if ($redisCpuUsage) { $detailInfo += " | 容器CPU: $redisCpuUsage" }
if ($redisMemUsage) { $detailInfo += " | 容器内存: $redisMemUsage" }
} else { } else {
$detailInfo += " | 容器: $detectedContainer | 端口: $detectedPort" $detailInfo += " | 容器: $detectedContainer | 端口: $detectedPort"
} }
...@@ -753,8 +793,72 @@ test -f "/root/#{SCRIPT_NAME}" && echo "/root/#{SCRIPT_NAME}" || echo NOT_FOUND ...@@ -753,8 +793,72 @@ test -f "/root/#{SCRIPT_NAME}" && echo "/root/#{SCRIPT_NAME}" || echo NOT_FOUND
$detailMsg = if ($isConnected) { "MySQL服务完全正常" } else { "MySQL检测失败" } $detailMsg = if ($isConnected) { "MySQL服务完全正常" } else { "MySQL检测失败" }
$detailMsg += " | 容器: $detectedContainer | 端口: $detectedPort" $detailMsg += " | 容器: $detectedContainer | 端口: $detectedPort"
# 提取MySQL详细指标
if ($isConnected) {
if ($mysqlVersion) { $detailMsg += " | 版本: $mysqlVersion" } if ($mysqlVersion) { $detailMsg += " | 版本: $mysqlVersion" }
# 提取连接数
if ($outputText -match '当前连接:\s*(\d+)') {
$detailMsg += " | 当前连接数: $($matches[1])"
}
# 提取总查询数
if ($outputText -match '总查询数:\s*([\d,]+)') {
$detailMsg += " | 总查询数: $($matches[1])"
}
# 提取QPS
if ($outputText -match '平均QPS:\s*([\d.]+)') {
$detailMsg += " | 平均QPS: $($matches[1])"
}
# 提取用户数据库数量
if ($outputText -match '用户数据库:\s*(\d+)\s*个') {
$detailMsg += " | 用户数据库: $($matches[1])个"
}
# 提取数据表总数
if ($outputText -match '数据表总数:\s*(\d+)\s*个') {
$detailMsg += " | 数据表总数: $($matches[1])个"
}
# 提取最大连接数
if ($outputText -match '最大连接数:\s*(\d+)') {
$detailMsg += " | 最大连接数: $($matches[1])"
}
# 提取缓冲池大小
if ($outputText -match '缓冲池大小:\s*(\d+\w+)') {
$detailMsg += " | 缓冲池: $($matches[1])"
}
# 提取字符集
if ($outputText -match '字符集:\s*(\w+)') {
$detailMsg += " | 字符集: $($matches[1])"
}
# 提取连接成功率
if ($outputText -match '连接成功率:\s*([\d.]+%)') {
$detailMsg += " | 连接成功率: $($matches[1])"
}
# 提取运行时间
if ($outputText -match '运行时间:\s*(\d+d\s*\d+h\s*\d*m)') {
$detailMsg += " | 运行时间: $($matches[1])"
}
# 提取CPU使用率
if ($outputText -match 'CPU使用率:\s*([\w.]+\s*%?)') {
$detailMsg += " | 容器CPU: $($matches[1])"
}
# 提取内存使用
if ($outputText -match '内存使用:\s*([\d.]+\s*%?\s*\([\w.]+\))') {
$detailMsg += " | 容器内存: $($matches[1])"
}
}
if ($isConnected) { if ($isConnected) {
Write-Log -Level "SUCCESS" -Message "[MySQL] $scriptName 执行成功" Write-Log -Level "SUCCESS" -Message "[MySQL] $scriptName 执行成功"
} else { } else {
......
...@@ -372,10 +372,19 @@ function Show-HealthReport { ...@@ -372,10 +372,19 @@ function Show-HealthReport {
} }
$icon = if ($r.Success) { "✅" } elseif ($r.Status -eq "跳过") { "ℹ️" } else { "❌" } $icon = if ($r.Success) { "✅" } elseif ($r.Status -eq "跳过") { "ℹ️" } else { "❌" }
$line = "- $icon $($r.Check): $($r.Status)"
if ($r.Details) { $line += " | $($r.Details)" } # 将 Details 按 " | " 拆分为多行展示,使报告更丰富易读
$md += $line $md += "- $icon $($r.Check): $($r.Status)"
Write-Host " $line" if ($r.Details) {
$detailParts = $r.Details -split ' \| '
foreach ($part in $detailParts) {
$trimmedPart = $part.Trim()
if ($trimmedPart) {
$md += " - $trimmedPart"
}
}
}
Write-Host " $icon $($r.Check): $($r.Status)"
} }
$md += "" $md += ""
Write-Host "" Write-Host ""
...@@ -401,22 +410,6 @@ function Show-HealthReport { ...@@ -401,22 +410,6 @@ function Show-HealthReport {
Write-Host "" Write-Host ""
} }
# 总结
Write-Host "==================================================================" -ForegroundColor Cyan
Write-Host "【检测总结】" -ForegroundColor Yellow
Write-Host " 总服务数: $totalServices"
Write-Host " 正常运行: $runningServices" -ForegroundColor Green
Write-Host " 异常服务: $failedServices" -ForegroundColor $(if ($failedServices -gt 0) { "Red" } else { "Green" })
$overallIcon = if ($failedServices -eq 0 -and $totalServices -gt 0) { "✅" } elseif ($failedServices -gt 0) { "❌" } else { "ℹ️" }
$md += "## 检测总结"
$md += "- 总服务数: $totalServices"
$md += "- 正常运行: $runningServices"
$md += "- 异常服务: $failedServices"
if ($failedServices -eq 0 -and $totalServices -gt 0) { Write-Host ""; Write-Host " 所有服务运行正常!" -ForegroundColor Green; $md += "- 结论: $overallIcon 所有服务运行正常!" }
elseif ($failedServices -gt 0) { Write-Host ""; Write-Host " 存在异常服务,请及时处理!" -ForegroundColor Red; $md += "- 结论: $overallIcon 存在异常服务,请及时处理!" }
elseif ($totalServices -eq 0) { Write-Host ""; Write-Host " 未检测到任何服务" -ForegroundColor Yellow; $md += "- 结论: $overallIcon 未检测到任何服务" }
# 配置文件与日志导出 # 配置文件与日志导出
if ($LogExportResults) { if ($LogExportResults) {
Write-Host "【配置文件与日志导出结果】" -ForegroundColor Yellow Write-Host "【配置文件与日志导出结果】" -ForegroundColor Yellow
...@@ -448,9 +441,8 @@ function Show-HealthReport { ...@@ -448,9 +441,8 @@ function Show-HealthReport {
Write-Host " 已导出服务 ($($LogExportResults.ExportedServices.Count) 个):" -ForegroundColor Green Write-Host " 已导出服务 ($($LogExportResults.ExportedServices.Count) 个):" -ForegroundColor Green
$md += "- 已导出服务 ($($LogExportResults.ExportedServices.Count) 个):" $md += "- 已导出服务 ($($LogExportResults.ExportedServices.Count) 个):"
foreach ($svc in $LogExportResults.ExportedServices) { foreach ($svc in $LogExportResults.ExportedServices) {
$fileList = ($svc.Files -join ', ') Write-Host " - $($svc.Name): $($svc.Files.Count) 项" -ForegroundColor Gray
Write-Host " - $($svc.Name): $($svc.Files.Count) 项 ($fileList)" -ForegroundColor Gray $md += " - $($svc.Name): $($svc.Files.Count) 项"
$md += " - $($svc.Name): $($svc.Files.Count) 项 ($fileList)"
} }
} }
...@@ -477,6 +469,22 @@ function Show-HealthReport { ...@@ -477,6 +469,22 @@ function Show-HealthReport {
Write-Host "" Write-Host ""
} }
# 总结
Write-Host "==================================================================" -ForegroundColor Cyan
Write-Host "【检测总结】" -ForegroundColor Yellow
Write-Host " 总服务数: $totalServices"
Write-Host " 正常运行: $runningServices" -ForegroundColor Green
Write-Host " 异常服务: $failedServices" -ForegroundColor $(if ($failedServices -gt 0) { "Red" } else { "Green" })
$overallIcon = if ($failedServices -eq 0 -and $totalServices -gt 0) { "✅" } elseif ($failedServices -gt 0) { "❌" } else { "ℹ️" }
$md += ""; $md += "## 检测总结"
$md += "- 总服务数: $totalServices"
$md += "- 正常运行: $runningServices"
$md += "- 异常服务: $failedServices"
if ($failedServices -eq 0 -and $totalServices -gt 0) { Write-Host ""; Write-Host " 所有服务运行正常!" -ForegroundColor Green; $md += "- 结论: $overallIcon 所有服务运行正常!" }
elseif ($failedServices -gt 0) { Write-Host ""; Write-Host " 存在异常服务,请及时处理!" -ForegroundColor Red; $md += "- 结论: $overallIcon 存在异常服务,请及时处理!" }
elseif ($totalServices -eq 0) { Write-Host ""; Write-Host " 未检测到任何服务" -ForegroundColor Yellow; $md += "- 结论: $overallIcon 未检测到任何服务" }
Write-Host "==================================================================" -ForegroundColor Cyan Write-Host "==================================================================" -ForegroundColor Cyan
Write-Host ""; Write-Host "日志文件: $LOG_FILE"; Write-Host "" Write-Host ""; Write-Host "日志文件: $LOG_FILE"; Write-Host ""
......
...@@ -76,25 +76,30 @@ ...@@ -76,25 +76,30 @@
- config目录 - config目录
- java2.0包:/data/services/api/java-meeting/java-meeting2.0 - java2.0包:/data/services/api/java-meeting/java-meeting2.0
- logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log - logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log
- config目录 - logs/目录下最近三天的历史日志文件,命名格式如 `ubains-INFO-AND-ERROR.2026-06-05.0.log.gz``ubains-ERROR.2026-06-04.0.log.gz`
- config目录下的.yml、.properties、.json、.js、.xml格式文件
- java-extapi包:/data/services/api/java-meeting/java-meeting-extapi - java-extapi包:/data/services/api/java-meeting/java-meeting-extapi
- logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log - logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log
- config目录 - logs/目录下最近三天的历史日志文件,命名格式如 `ubains-INFO-AND-ERROR.2026-06-05.0.log.gz``ubains-ERROR.2026-06-04.0.log.gz`
- config目录下的.yml、.properties、.json、.js、.xml格式文件
- java-scheduling包:/data/services/api/java-meeting/java-message-scheduling - java-scheduling包:/data/services/api/java-meeting/java-message-scheduling
- logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log - logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log
- config目录 - logs/目录下最近三天的历史日志文件,命名格式如 `ubains-INFO-AND-ERROR.2026-06-05.0.log.gz``ubains-ERROR.2026-06-04.0.log.gz`
- config目录下的.yml、.properties、.json、.js、.xml格式文件
- java-mqtt包:/data/services/api/java-meeting/java-mqtt - java-mqtt包:/data/services/api/java-meeting/java-mqtt
- logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log - logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log
- config目录 - logs/目录下最近三天的历史日志文件,命名格式如 `ubains-INFO-AND-ERROR.2026-06-05.0.log.gz``ubains-ERROR.2026-06-04.0.log.gz`
- config目录下的.yml、.properties、.json、.js、.xml格式文件
- java-quartz包:/data/services/api/java-meeting/java-quartz - java-quartz包:/data/services/api/java-meeting/java-quartz
- logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log - logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log
- config目录 - logs/目录下最近三天的历史日志文件,命名格式如 `ubains-INFO-AND-ERROR.2026-06-05.0.log.gz``ubains-ERROR.2026-06-04.0.log.gz`
- config目录下的.yml、.properties、.json、.js、.xml格式文件
- cmdb包:/data/services/api/python-cmdb - cmdb包:/data/services/api/python-cmdb
- log/uinfo.log、log/error.log和log/uwsgi.log - log/目录下最近三天的日志文件,当前日志命名格式如 `uinfo.log``error.log``uwsgi.log`,历史日志命名格式如 `uinfo.log.1``uinfo.log.2``error.log.1`
- setting.conf - setting.conf
- cmdb/bus/config/settingbus.conf - cmdb/bus/config/settingbus.conf
- voice包:/data/services/api/python-voice - voice包:/data/services/api/python-voice
- log/uinfo.log和log/uwsgi.log - log/目录下最近三天的日志文件,当前日志命名格式如 `uinfo.log``uwsgi.log`,历史日志命名格式如 `uinfo.log.1``uinfo.log.2`
- setting.conf - setting.conf
- uvoice/bus/config/settingbus.conf - uvoice/bus/config/settingbus.conf
...@@ -141,10 +146,12 @@ ...@@ -141,10 +146,12 @@
#### 后端服务目录: #### 后端服务目录:
- 预定2.0后端:/var/www/java/api-java-meeting2.0 - 预定2.0后端:/var/www/java/api-java-meeting2.0
- logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log - logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log
- config目录 - logs/目录下最近三天的历史日志文件,命名格式如 `ubains-INFO-AND-ERROR.2026-06-05.0.log.gz``ubains-ERROR.2026-06-04.0.log.gz`
- config目录下的.yml、.properties、.json、.js、.xml格式文件
- 预定对外后端:/var/www/java/external-meeting-api - 预定对外后端:/var/www/java/external-meeting-api
- logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log - logs/ubains-INFO-AND-ERROR.log、logs/ubains-ERROR.log
- config目录 - logs/目录下最近三天的历史日志文件,命名格式如 `ubains-INFO-AND-ERROR.2026-06-05.0.log.gz``ubains-ERROR.2026-06-04.0.log.gz`
- config目录下的.yml、.properties、.json、.js、.xml格式文件
- 运维后端:/var/www/html - 运维后端:/var/www/html
- setting.conf - setting.conf
- log/uinfo.log、log/error.log和log/uwsgi.log - log/uinfo.log、log/error.log和log/uwsgi.log
......
...@@ -84,13 +84,13 @@ ...@@ -84,13 +84,13 @@
| auth-sso-auth | `/data/services/api/auth/auth-sso-auth` | `log.out`, `config/` | | auth-sso-auth | `/data/services/api/auth/auth-sso-auth` | `log.out`, `config/` |
| auth-sso-gatway | `/data/services/api/auth/auth-sso-gatway` | `log.out`, `config/` | | auth-sso-gatway | `/data/services/api/auth/auth-sso-gatway` | `log.out`, `config/` |
| auth-sso-system | `/data/services/api/auth/auth-sso-system` | `log.out`, `config/` | | auth-sso-system | `/data/services/api/auth/auth-sso-system` | `log.out`, `config/` |
| java-meeting2.0 | `/data/services/api/java-meeting/java-meeting2.0` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `config/` | | java-meeting2.0 | `/data/services/api/java-meeting/java-meeting2.0` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `logs/``ubains-INFO-AND-ERROR.*.log.gz`最近3天, `config/`(仅 .yml/.properties/.json/.js/.xml) |
| java-meeting-extapi | `/data/services/api/java-meeting/java-meeting-extapi` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `config/` | | java-meeting-extapi | `/data/services/api/java-meeting/java-meeting-extapi` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `logs/``ubains-INFO-AND-ERROR.*.log.gz`最近3天, `config/`(仅 .yml/.properties/.json/.js/.xml) |
| java-message-scheduling | `/data/services/api/java-meeting/java-message-scheduling` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `config/` | | java-message-scheduling | `/data/services/api/java-meeting/java-message-scheduling` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `logs/``ubains-INFO-AND-ERROR.*.log.gz`最近3天, `config/`(仅 .yml/.properties/.json/.js/.xml) |
| java-mqtt | `/data/services/api/java-meeting/java-mqtt` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `config/` | | java-mqtt | `/data/services/api/java-meeting/java-mqtt` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `logs/``ubains-INFO-AND-ERROR.*.log.gz`最近3天, `config/`(仅 .yml/.properties/.json/.js/.xml) |
| java-quartz | `/data/services/api/java-meeting/java-quartz` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `config/` | | java-quartz | `/data/services/api/java-meeting/java-quartz` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `logs/``ubains-INFO-AND-ERROR.*.log.gz`最近3天, `config/`(仅 .yml/.properties/.json/.js/.xml) |
| python-cmdb | `/data/services/api/python-cmdb` | `log/uinfo.log`, `log/error.log`, `log/uwsgi.log`, `setting.conf`, `cmdb/bus/config/settingbus.conf` | | python-cmdb | `/data/services/api/python-cmdb` | `log/`目录最近3天(`uinfo.log``uinfo.log.1``error.log``uwsgi.log`等), `setting.conf`, `cmdb/bus/config/settingbus.conf` |
| python-voice | `/data/services/api/python-voice` | `log/uinfo.log`, `log/uwsgi.log`, `setting.conf`, `uvoice/bus/config/settingbus.conf` | | python-voice | `/data/services/api/python-voice` | `log/`目录最近3天(`uinfo.log``uinfo.log.1``uwsgi.log`等), `setting.conf`, `uvoice/bus/config/settingbus.conf` |
**新统一平台 - 中间件服务(4项):** **新统一平台 - 中间件服务(4项):**
...@@ -124,8 +124,8 @@ ...@@ -124,8 +124,8 @@
| 服务名称 | 服务根目录 | 导出文件 | | 服务名称 | 服务根目录 | 导出文件 |
|----------|-----------|---------| |----------|-----------|---------|
| api-java-meeting2.0 | `/var/www/java/api-java-meeting2.0` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `config/` | | api-java-meeting2.0 | `/var/www/java/api-java-meeting2.0` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `logs/timeFile/`(最近3天 .log.gz), `config/`(仅 .yml/.properties/.json/.js/.xml) |
| external-meeting-api | `/var/www/java/external-meeting-api` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `config/` | | external-meeting-api | `/var/www/java/external-meeting-api` | `logs/ubains-INFO-AND-ERROR.log`, `logs/ubains-ERROR.log`, `logs/timeFile/`(最近3天 .log.gz), `config/`(仅 .yml/.properties/.json/.js/.xml) |
| html-ops | `/var/www/html` | `setting.conf`, `log/uinfo.log`, `log/error.log`, `log/uwsgi.log` | | html-ops | `/var/www/html` | `setting.conf`, `log/uinfo.log`, `log/error.log`, `log/uwsgi.log` |
**传统平台 - 中间件服务(5项):** **传统平台 - 中间件服务(5项):**
...@@ -172,10 +172,12 @@ ...@@ -172,10 +172,12 @@
- 检查服务根目录是否存在于远程服务器(`test -d` - 检查服务根目录是否存在于远程服务器(`test -d`
- 不存在 → 记录到 `SkippedServices`,继续下一个 - 不存在 → 记录到 `SkippedServices`,继续下一个
- 存在 → 创建 `/tmp/config_and_log/<服务名称>/` 子目录 - 存在 → 创建 `/tmp/config_and_log/<服务名称>/` 子目录
- 逐项导出文件/目录: - 逐项导出文件/目录(Files 数组支持字符串和哈希表两种格式):
- 单文件:`cp <源文件> /tmp/config_and_log/<服务名称>/` - **字符串 - 单文件**`cp <源文件> /tmp/config_and_log/<服务名称>/`
- 目录:`cp -r <源目录> /tmp/config_and_log/<服务名称>/` - **字符串 - 目录**`cp -r <源目录> /tmp/config_and_log/<服务名称>/`
- 通配符(如 `*.conf`):`cp <通配符> /tmp/config_and_log/<服务名称>/` - **字符串 - 通配符**(如 `*.conf`):`cp <通配符> /tmp/config_and_log/<服务名称>/`
- **哈希表 - ext-filter 类型**(config 目录扩展名过滤):仅复制目录中 `.yml/.properties/.json/.js/.xml` 格式文件,使用 `find` + 扩展名匹配
- **哈希表 - mtime 类型**(timeFile 目录时间过滤):仅复制最近 N 天修改过的文件,使用 `find -mtime -N`
- 导出失败 → 记录到 `FailedServices`,继续 - 导出失败 → 记录到 `FailedServices`,继续
5. **远程压缩** - `tar -czf /tmp/<IP>_<时间>.tar.gz -C /tmp config_and_log` 5. **远程压缩** - `tar -czf /tmp/<IP>_<时间>.tar.gz -C /tmp config_and_log`
6. **下载到本地** - 通过 pscp 下载到 `$SCRIPT_DIR/config_and_log/` 6. **下载到本地** - 通过 pscp 下载到 `$SCRIPT_DIR/config_and_log/`
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论