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

refactor(scripts): 优化服务自检脚本的日志导出和容器信息展示逻辑

- 重构 Redis 和 Emqx 日志导出的状态判断逻辑,使用变量替代三元运算符
- 简化 Nginx 日志导出的远程脚本,使用单引号 here-string 避免 PowerShell 解析问题
- 移除 Nginx 日志导出中多余的注释行
- 优化变量赋值的代码格式,增加可读性
- 调整容器信息展示逻辑,从详细信息展示改为状态汇总展示
- 移除复杂的容器详情展示代码,简化为状态图标和名称显示
- 新增 Download-RemoteFile 函数,统一文件下载逻辑
- 添加 PlatformType 全局变量设置,供容器信息检测使用
上级 46594253
......@@ -1679,10 +1679,13 @@ function Test-ContainerInformation {
Write-Log -Level "WARN" -Message "[Redis] redis.log 导出异常:$($_.Exception.Message)"
}
$statusText = if ($exportOk) { "完成" } else { "失败" }
$detailText = if ($exportOk) { "redis.log 导出成功 -> $localRedisLog" } else { "redis.log 导出失败或文件不存在 ($redisLogPath)" }
$results += @{
Check = "Redis日志导出"
Status = ($exportOk ? "完成" : "失败")
Details = $exportOk ? "redis.log 导出成功 -> $localRedisLog" : "redis.log 导出失败或文件不存在 ($redisLogPath)"
Status = $statusText
Details = $detailText
Success = $exportOk
}
......@@ -1798,10 +1801,13 @@ function Test-ContainerInformation {
Write-Log -Level "WARN" -Message "[Emqx] emqx.log.1 导出异常:$($_.Exception.Message)"
}
$emqxStatusText = if ($emqxExportOk) { "完成" } else { "失败" }
$emqxDetailText = if ($emqxExportOk) { "emqx.log.1 导出成功 -> $localEmqxLog" } else { "emqx.log.1 导出失败或文件不存在 ($emqxLogPath)" }
$results += @{
Check = "Emqx日志导出"
Status = ($emqxExportOk ? "完成" : "失败")
Details = $emqxExportOk ? "emqx.log.1 导出成功 -> $localEmqxLog" : "emqx.log.1 导出失败或文件不存在 ($emqxLogPath)"
Status = $emqxStatusText
Details = $emqxDetailText
Success = $emqxExportOk
}
......@@ -2019,41 +2025,10 @@ function Export-ServiceLogs {
$localNginxLog = Join-Path $exportDir "nginx_error.log"
# 步骤1:在远端通过 docker cp 将容器内 /usr/local/nginx/logs/error.log 拷贝到宿主机
$remoteScript = @"
set -e
# 检查是否存在 ujava 容器
if ! docker ps --format '{{.Names}}' | grep -E 'ujava' >/dev/null 2>&1; then
echo '[Nginx] 未检测到 ujava 容器,跳过 Nginx 日志导出。'
exit 0
fi
mkdir -p '$remoteTmpDir'
# 优先使用系统识别到的 ujava 容器名(例如 ujava2)
UJAVA_CONTAINER="$($SystemInfo.UjavaContainer)"
if [ -z "\$UJAVA_CONTAINER" ]; then
# 兜底:取第一个匹配 'ujava' 的容器
UJAVA_CONTAINER=\$(docker ps --format '{{.Names}}' | grep -m 1 'ujava' || true)
fi
if [ -z "\$UJAVA_CONTAINER" ]; then
echo '[Nginx] 未找到可用的 ujava 容器名称,无法导出 Nginx 日志。'
exit 1
fi
echo "[Nginx] 使用容器 \$UJAVA_CONTAINER 导出 /usr/local/nginx/logs/error.log ..."
if ! docker cp "\$UJAVA_CONTAINER:/usr/local/nginx/logs/error.log" '$remoteTmpFile' 2>/tmp/nginx_cp_err.log; then
echo '[Nginx] docker cp 失败,无法从容器内拷贝 error.log,详情如下:'
if [ -f /tmp/nginx_cp_err.log ]; then
cat /tmp/nginx_cp_err.log
fi
exit 1
fi
echo "[Nginx] 已将容器内 /usr/local/nginx/logs/error.log 拷贝到宿主机: $remoteTmpFile"
"@
# 注意:这里用单引号 here-string,避免 PowerShell 解析 $ 和 $(...) 等
$remoteScript = @'
HAS_UJAVA=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -E 'ujava' | head -n 1); if [ -z "$HAS_UJAVA" ]; then echo "[Nginx] 未检测到 ujava 容器,跳过 Nginx 日志导出。"; exit 0; fi; mkdir -p /tmp; if docker ps --format '{{.Names}}' 2>/dev/null | grep -w 'ujava2' >/dev/null 2>&1; then UJAVA_CONTAINER="ujava2"; else UJAVA_CONTAINER=$(docker ps --format '{{.Names}}' 2>/dev/null | grep 'ujava' | head -n 1); fi; if [ -z "$UJAVA_CONTAINER" ]; then echo "[Nginx] 未找到可用的 ujava 容器名称,无法导出 Nginx 日志。"; exit 1; fi; echo "[Nginx] 使用容器 $UJAVA_CONTAINER 导出 /usr/local/nginx/logs/error.log ..."; docker cp "$UJAVA_CONTAINER:/usr/local/nginx/logs/error.log" "/tmp/nginx_error.log" 2>/tmp/nginx_cp_err.log; RET=$?; if [ $RET -ne 0 ]; then echo "[Nginx] docker cp 失败,无法从容器内拷贝 error.log,详情如下:"; if [ -f /tmp/nginx_cp_err.log ]; then cat /tmp/nginx_cp_err.log; fi; exit $RET; fi; echo "[Nginx] 已将容器内 /usr/local/nginx/logs/error.log 拷贝到宿主机: /tmp/nginx_error.log"
'@
$cpRes = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $remoteScript
$cpOutput = ($cpRes.Output | Out-String).Trim()
......@@ -2071,7 +2046,6 @@ echo "[Nginx] 已将容器内 /usr/local/nginx/logs/error.log 拷贝到宿主机
}
}
elseif ($cpOutput -match "未检测到 ujava 容器,跳过 Nginx 日志导出") {
# 配置有要求:仅在存在 ujava 容器时导出 Nginx 日志
Write-Log -Level "WARN" -Message "[Nginx] 未检测到 ujava 容器,本次跳过 Nginx 日志导出。"
}
else {
......@@ -2089,18 +2063,18 @@ echo "[Nginx] 已将容器内 /usr/local/nginx/logs/error.log 拷贝到宿主机
)
try {
$dlOut = & $script:PSCP_PATH @pscpArgs2 2>&1
$dlOut = & $script:PSCP_PATH @pscpArgs2 2>&1
$dlCode = $LASTEXITCODE
if ($dlCode -ne 0 -and ($dlOut -match "host key" -or $dlOut -match "Cannot confirm")) {
$cmdLine2 = "echo y | `"$($script:PSCP_PATH)`" -scp -batch -P $($Server.Port) -l $($Server.User) -pw `"$($Server.Pass)`" `"$($Server.User)@$($Server.IP):$remoteTmpFile`" `"$localNginxLog`""
Write-Log -Level "WARN" -Message "[Nginx] 检测到主机密钥提示,自动接受并重试: $cmdLine2"
$dlOut = cmd /c $cmdLine2 2>&1
$dlOut = cmd /c $cmdLine2 2>&1
$dlCode = $LASTEXITCODE
}
if ($dlCode -eq 0 -and (Test-Path $localNginxLog)) {
$sz = (Get-Item $localNginxLog).Length
$sz = (Get-Item $localNginxLog).Length
$szKB = [math]::Round($sz / 1024, 2)
Write-Log -Level "SUCCESS" -Message "[Nginx] nginx_error.log 导出成功 ($szKB KB): $localNginxLog"
$exportedFiles += @{
......@@ -2473,72 +2447,46 @@ function Show-HealthReport {
} else { Write-Host " 未执行" -ForegroundColor Yellow; $md += "- 总结: ℹ️ 未执行" }
$md += ""
# 容器信息
# 容器信息
$md += "## 容器信息"
if (-not $ContainerInfo -or $ContainerInfo.Count -eq 0) {
Write-Host "【容器信息】未发现容器或容器运行时不可用" -ForegroundColor Yellow
$md += "- 未发现容器或容器运行时不可用"
} else {
$runningCount = ($ContainerInfo | Where-Object { $_.Running }).Count
$stoppedCount = $ContainerInfo.Count - $runningCount
Write-Host "【容器信息】总数: $($ContainerInfo.Count) | 运行中: $runningCount | 已停止: $stoppedCount" -ForegroundColor Yellow
$md += "- 容器总数: $($ContainerInfo.Count)"
$md += "- 运行中: $runningCount"
$md += "- 已停止: $stoppedCount"
foreach ($c in $ContainerInfo) {
$statusIcon = if ($c.Running) { "✅" } else { "⛔" }
$ip = if ($c.IPAddress) { $c.IPAddress } else { "-" }
$health = if ($c.Health) { $c.Health } else { "-" }
$rp = if ($c.RestartPolicy) { $c.RestartPolicy } else { "-" }
$rc = if ($c.RestartCount -ne $null) { $c.RestartCount } else { "-" }
$ports = @(); if ($c.Ports -and $c.Ports.Count -gt 0) { $ports = $c.Ports }
$nets = @(); if ($c.Networks -and $c.Networks.Count -gt 0) { $nets = $c.Networks }
$showPorts = if ($ports.Count -gt 6) { ($ports | Select-Object -First 6) + "..." } else { $ports }
$showNets = if ($nets.Count -gt 6) { ($nets | Select-Object -First 6) + "..." } else { $nets }
$mountsStr = '-'
if ($c.Mounts -and $c.Mounts.Count -gt 0) {
$showMounts = if ($c.Mounts.Count -gt 3) { ($c.Mounts | Select-Object -First 3) + '...' } else { $c.Mounts }
$mountsStr = ($showMounts -join '; ')
}
# 这里的 ContainerInfo 实际就是 Test-ContainerInformation 返回的 $results,
# 其中只包含一条汇总记录和若干其他检查记录。
# 我们只按 Status 文本做一个简单统计展示。
$total = $ContainerInfo.Count
# 粗略认为 Status 含“运行中”或 “Up” 就算运行;这取决于你写入 Details 的习惯
$runningCount = ($ContainerInfo | Where-Object {
($_ -is [hashtable] -or $_ -is [pscustomobject]) -and $_.Status -match '完成|运行中|Up'
}).Count
$stoppedCount = $total - $runningCount
Write-Host "【容器信息】记录条数: $total" -ForegroundColor Yellow
$md += "- 记录条数: $total"
$szParts = @()
if ($c.SizeRw -ne $null) { $szParts += ("rw={0}" -f $c.SizeRw) }
if ($c.SizeRootFs -ne $null) { $szParts += ("root={0}" -f $c.SizeRootFs) }
$szStr = if ($szParts.Count -gt 0) { ($szParts -join ', ') } else { '-' }
$md += "- $statusIcon 名称: $($c.Name) | 镜像: $($c.Image) | 状态: $($c.Status) | 健康: $health | 重启: $rp/$rc | IP: $ip"
$portsStr = '-'
if ($null -ne $showPorts) {
if ($showPorts -is [string]) {
$portsStr = $showPorts
} else {
$tmp = @($showPorts)
if ($tmp.Count -gt 0) { $portsStr = ($tmp -join ', ') }
}
}
$netsStr = '-'
if ($null -ne $showNets) {
if ($showNets -is [string]) {
$netsStr = $showNets
} else {
$tmpn = @($showNets)
if ($tmpn.Count -gt 0) { $netsStr = ($tmpn -join ', ') }
}
}
foreach ($c in $ContainerInfo) {
# 兼容 hashtable / pscustomobject
$name = $null
$status = $null
if ($c -is [hashtable]) {
if ($c.ContainsKey('Check')) { $name = $c['Check'] }
if ($c.ContainsKey('Status')) { $status = $c['Status'] }
} else {
$name = $c.Check
$status = $c.Status
}
$md += " - 端口: $portsStr"
$md += " - 网络: $netsStr"
if ($mountsStr -ne '-') { $md += " - 挂载: $mountsStr" }
$md += " - 大小: $szStr"
if (-not $name -and -not $status) { continue }
# 在容器之间插入 Markdown 分割线
$md += "---"
}
$icon = if ($status -match '完成|正常|运行中|Up') { "✅" } else { "⚠️" }
# 这里避免在双引号内出现 $name: 这样的形式,使用 -f 拼接
$line = ("- {0} {1}: {2}" -f $icon, $name, $status)
$md += $line
Write-Host " $line"
}
}
$md += ""
......@@ -2918,6 +2866,59 @@ function Check-FilePermissions {
return @{ Summary = $summaryText; Lines = $lines }
}
# ================================
# 从远端下载文件到本地(基于 pscp)
# ================================
function Download-RemoteFile {
param(
[Parameter(Mandatory=$true)] [hashtable]$Server,
[Parameter(Mandatory=$true)] [string]$RemotePath,
[Parameter(Mandatory=$true)] [string]$LocalPath
)
if (-not $script:PSCP_PATH -or -not (Test-Path $script:PSCP_PATH)) {
Write-Log -Level "ERROR" -Message "[DL] pscp.exe 未找到,无法下载文件: $RemotePath"
return @{ Success = $false; Reason = "pscp not found" }
}
$localDir = Split-Path $LocalPath -Parent
if (-not (Test-Path $localDir)) {
New-Item -ItemType Directory -Path $localDir -Force | Out-Null
}
$args = @(
"-scp",
"-batch",
"-P", $Server.Port,
"-l", $Server.User,
"-pw", $Server.Pass,
"$($Server.User)@$($Server.IP):$RemotePath",
$LocalPath
)
Write-Log -Level "INFO" -Message ("[DL] pscp 下载: {0} {1}" -f $script:PSCP_PATH, ($args -join ' '))
$out = & $script:PSCP_PATH @args 2>&1
$code = $LASTEXITCODE
if ($code -ne 0 -and ($out -match "host key" -or $out -match "Cannot confirm")) {
$cmdLine = "echo y | `"$($script:PSCP_PATH)`" -scp -batch -P $($Server.Port) -l $($Server.User) -pw `"$($Server.Pass)`" `"$($Server.User)@$($Server.IP):$RemotePath`" `"$LocalPath`""
Write-Log -Level "WARN" -Message "[DL] 首次连接,接受主机密钥并重试: $cmdLine"
$out = cmd /c $cmdLine 2>&1
$code = $LASTEXITCODE
}
if ($code -eq 0 -and (Test-Path $LocalPath)) {
$size = (Get-Item $LocalPath).Length
Write-Log -Level "SUCCESS" -Message "[DL] 下载成功 ($([math]::Round($size/1024,2)) KB): $LocalPath"
return @{ Success = $true; Size = $size; Output = $out }
} else {
$oneLine = ($out -join " ") -replace '\s+', ' '
Write-Log -Level "ERROR" -Message "[DL] 下载失败 ExitCode=$code, 输出: $oneLine"
return @{ Success = $false; ExitCode = $code; Output = $out }
}
}
# ================================
# 远程复制辅助函数(pscp 优先)
# ================================
......@@ -3269,6 +3270,7 @@ function Main {
# 检测平台类型
$platformType = Get-PlatformType -Server $server
$Global:PlatformType = $platformType # 新增:供 Test-ContainerInformation 使用
Write-Host ""
# 检测系统类型
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论