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

feat(server-check): 增强服务自检功能

- 重构容器信息收集逻辑,简化容器状态检查
- 新增 Redis 容器异常检测和自动修复功能
- 添加 Redis 日志导出到本地功能
- 实现 Redis 容器修复后的复检机制
- 扩展修复脚本支持 redis_container_exception 操作
- 更新上传修复脚本函数支持 Redis 异常处理
- 添加服务自检使用说明文档
- 优化代码结构和错误处理机制
上级 a68401ba
......@@ -655,3 +655,16 @@ cd /data/services/api/java-meeting/java-meeting-extapi/
- 添加DNS服务器前会检查是否已存在,避免重复配置
- 当自动处理失败时,会提供具体的手动操作指导
- 会根据检测到的网络管理器类型选择相应的服务管理方式
### 11. 修复服务器redis文件损坏问题处理
函数名称:redis_container_exception
需求说明:
修复redis容器启动异常问题
修复步骤:
1、检测新旧平台
2、重启redis查看是否正常重启成功,如果容器重启失败则往下执行第3步骤。
3、删除redis容器的data下所有数据
旧平台:
路径:/var/www/redis/data,将此目录下数据删除后重启uredis容器
新统一平台:
路径:/data/middleware/redis/data,将此目录下数据删除后重启uredis容器
\ No newline at end of file
......@@ -1985,6 +1985,121 @@ show_disk_partition_info() {
log_info "磁盘分区调整参考信息显示完成"
}
# 补充redis服务异常时修复操作
redis_container_exception() {
log_info "开始修复 redis 容器启动异常问题"
# 1. 检测平台类型(new / standard / unknown)
local platform
platform=$(detect_platform)
log_info "检测到平台类型: $platform"
# 2. 检查 docker 与 uredis 容器
if ! command -v docker >/dev/null 2>&1; then
log_error "系统中未安装 docker,无法处理 redis 容器异常"
show_operation_summary "修复 redis 容器异常" "${RED}失败${NC} (未安装 docker)"
return 1
fi
if ! docker ps -a --format '{{.Names}}' | grep -q '^uredis$'; then
log_error "未找到 uredis 容器,请确认 redis 容器已创建"
show_operation_summary "修复 redis 容器异常" "${RED}失败${NC} (未找到 uredis 容器)"
return 1
fi
# 3. 先尝试正常重启 uredis 容器
log_info "尝试重启 uredis 容器..."
if docker restart uredis >/dev/null 2>&1; then
sleep 5
if docker ps --format '{{.Names}}' | grep -q '^uredis$'; then
log_info "uredis 容器重启成功,无需清理数据"
show_operation_summary "修复 redis 容器异常" "${GREEN}完成${NC} (容器重启成功)"
return 0
else
log_warn "uredis 容器重启后未处于运行状态,将按 PRD 执行数据清理流程"
fi
else
log_warn "直接重启 uredis 容器失败,将按 PRD 执行数据清理流程"
fi
# 4. 确定 redis data 目录(按平台分支)
local redis_data_dir=""
if [ "$platform" = "new" ]; then
redis_data_dir="/data/middleware/redis/data"
elif [ "$platform" = "standard" ]; then
redis_data_dir="/var/www/redis/data"
else
# 未识别平台时,根据目录存在性猜测
if [ -d "/data/middleware/redis/data" ]; then
redis_data_dir="/data/middleware/redis/data"
log_warn "平台类型 unknown,使用新平台 redis data 目录: $redis_data_dir"
elif [ -d "/var/www/redis/data" ]; then
redis_data_dir="/var/www/redis/data"
log_warn "平台类型 unknown,使用旧平台 redis data 目录: $redis_data_dir"
else
log_error "无法确定 redis data 目录,请确认平台及目录结构"
show_operation_summary "修复 redis 容器异常" "${RED}失败${NC} (未找到 redis data 目录)"
return 1
fi
fi
log_info "将使用 redis data 目录: $redis_data_dir"
if [ ! -d "$redis_data_dir" ]; then
log_error "redis data 目录不存在: $redis_data_dir"
show_operation_summary "修复 redis 容器异常" "${RED}失败${NC} (redis data 目录不存在)"
return 1
fi
# 5. 确认是否清空 redis data 目录(支持非交互)
local do_clear_data=false
log_warn "准备删除 redis data 目录下所有数据,这将清空当前 redis 数据。"
log_info "目录: $redis_data_dir"
if [ "$NON_INTERACTIVE" = "1" ] && [ "$ASSUME_YES" = "1" ]; then
log_info "非交互模式,自动确认清空 redis data 目录"
do_clear_data=true
else
if confirm_action "是否确认删除该目录下所有数据并重新启动 uredis 容器?"; then
do_clear_data=true
else
log_info "用户取消删除 redis data 数据"
fi
fi
if [ "$do_clear_data" != true ]; then
show_operation_summary "修复 redis 容器异常" "${YELLOW}取消${NC} (用户取消删除数据)"
return 0
fi
# 6. 停止容器并清空数据目录
log_info "停止 uredis 容器..."
docker stop uredis >/dev/null 2>&1 || log_warn "停止 uredis 容器失败,可能已停止"
log_info "清空 redis data 目录内容: $redis_data_dir"
# 防止变量为空导致 rm -rf / 等危险:加 :? 保护
rm -rf "${redis_data_dir:?}/"* "${redis_data_dir:?}"/.[!.]* "${redis_data_dir:?}"/..?* 2>/dev/null || true
# 7. 重启 uredis 容器
log_info "重新启动 uredis 容器..."
if docker start uredis >/dev/null 2>&1; then
sleep 5
if docker ps --format '{{.Names}}' | grep -q '^uredis$'; then
log_info "uredis 容器已在清空数据后成功启动"
show_operation_summary "修复 redis 容器异常" "${GREEN}完成${NC} (已清空 data 并重启 uredis)"
return 0
else
log_error "清空数据后 uredis 容器仍未处于运行状态,请检查容器日志"
show_operation_summary "修复 redis 容器异常" "${RED}失败${NC} (清空 data 后容器仍未运行)"
return 1
fi
else
log_error "清空数据后启动 uredis 容器失败,请检查 docker / 容器配置"
show_operation_summary "修复 redis 容器异常" "${RED}失败${NC} (docker start uredis 失败)"
return 1
fi
}
# 动作分发:根据动作名调用对应函数(必要时传入平台)
run_action_by_name() {
local action="$1"
......@@ -2033,6 +2148,9 @@ run_action_by_name() {
fix_dns_config)
fix_dns_config "$platform"
;;
redis_container_exception)
redis_container_exception
;;
# 备份
backup_environment_data|backup_env)
......
......@@ -244,11 +244,30 @@
2、数据库备份,账号为root,密码为dNrprU&2S,数据库容器是umysql容器,数据库是ubains和devops,数据库备份完成后也复制到/home/bakup目录下
最后将/home/bakup目录压缩成tar.gz格式文件并导出,文件命名补充时间戳,导出完成后清理/home目录下的这个备份文件。
##### 12、容器信息收集(✅ 已实现):
函数名称:Test-ContainerInformation
需求描述:
查询当前服务器上所有容器信息(包含未运行与运行中的信息),可以通过docker inspect来获取MAC地址、端口映射信息、启动文件位置。
信息打印排版:先打印运行中的容器信息,再打印未运行的容器信息。在容器信息打印之间增加分隔线。
容器异常:
Redis容器:
1、日志获取:
检测
新统一平台:
路径:/data/middleware/redis/data/redis.log
传统平台:
路径:/var/www/redis/data/redis.log
将上述redis.log文件从目标服务器导出到本地自检结果目录中(例如logs/redis/子目录),并在自检日志中记录导出结果。
2、异常判定:
如果 uredis 容器未运行,并且没有其他名字中包含“redis”的运行中容器,则判定为 Redis 容器异常。
3、远端修复操作:
调用上传修复脚本函数 Upload_the_repair_script,将当前目录下的issue_handler.sh脚本上传到目标服务器,并执行其中的 redis_container_exception 修复函数。
调用示例(逻辑示意):
./issue_handler.sh --action redis_container_exception --non-interactive --yes
4、修复完成后的复检:
修复脚本执行完成后,再次检查 uredis 容器状态:
- 如果 uredis 已处于运行状态,记录“Redis容器复检成功”到自检日志和md报告中;
- 如果 uredis 仍未运行,则记录“Redis容器复检失败,需要人工排查”到自检日志和md报告中。
##### 13、定时任务查询(待实现):
函数名称:Test-ScheduledTask
......@@ -262,7 +281,6 @@
ujava存在:
-
##### 14、上传修复脚本(已实现NTP和防火墙修复):
函数名称:Upload_the_repair_script
......
......@@ -1575,211 +1575,208 @@ function Test-ContainerInformation {
param(
[hashtable]$Server
)
Write-Host ""
Write-Log -Level "INFO" -Message "========== 容器信息收集 =========="
$results = @()
# 运行时检测(docker 优先,兼容 podman)
$runtime = 'docker'
$rtCheck = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command "docker --version 2>/dev/null || echo DOCKER_NOT_FOUND"
if ($rtCheck.Output -match 'DOCKER_NOT_FOUND' -or $rtCheck.ExitCode -ne 0) {
$rtCheck2 = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command "podman --version 2>/dev/null || echo PODMAN_NOT_FOUND"
if ($rtCheck2.Output -match 'PODMAN_NOT_FOUND' -or $rtCheck2.ExitCode -ne 0) {
Write-Log -Level "WARN" -Message "目标服务器未检测到 Docker/Podman,跳过容器信息收集"
# 1. 查询所有容器信息(运行 + 未运行)
$cmd = "docker ps -a --format '{{.ID}} {{.Names}} {{.Status}}'"
$dockerInfo = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $cmd
if ($dockerInfo.ExitCode -ne 0) {
Write-Log -Level "ERROR" -Message " 无法获取容器信息:$($dockerInfo.Error -join ' ')"
$results += @{
Check = "容器信息收集"
Status = "失败"
Details = "docker ps -a 执行失败"
Success = $false
}
return $results
}
$runningContainers = @()
$stoppedContainers = @()
foreach ($line in $dockerInfo.Output) {
if (-not $line.Trim()) { continue }
# 简单解析:ID NAME STATUS...
$parts = $line -split '\s+', 3
if ($parts.Count -lt 3) { continue }
$id = $parts[0]
$name = $parts[1]
$status = $parts[2]
# 可以在这里按需补充 docker inspect 获取 MAC/端口/启动命令等(如已有可保留)
$item = [ordered]@{
Id = $id
Name = $name
Status = $status
}
if ($status -match '^Up') {
$runningContainers += $item
} else {
$runtime = 'podman'
Write-Log -Level "INFO" -Message "检测到 Podman 作为容器运行时"
$stoppedContainers += $item
}
}
# 获取所有容器(ID 与 Name)
$listCmd = "$runtime ps -a --format '{{.ID}} {{.Names}}' 2>/dev/null || true"
$listResult = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $listCmd
$lines = $listResult.Output -split "`n" | Where-Object { $_ -match '\S' } | ForEach-Object { $_.Trim() }
if (-not $lines -or $lines.Count -eq 0) {
Write-Log -Level "INFO" -Message "未发现任何容器"
return $results
# 2. 容器信息导出排版:先运行,再未运行,中间加分隔线(写入日志,最终导出到 md)
Write-Log -Level "INFO" -Message "----- 运行中的容器 -----"
foreach ($c in $runningContainers) {
Write-Log -Level "INFO" -Message (" [RUNNING] {0} ({1}) - {2}" -f $c.Name, $c.Id, $c.Status)
}
$idNameMap = @{}
foreach ($line in $lines) {
$parts = $line -split ' ', 2
if ($parts.Count -eq 2) { $idNameMap[$parts[0]] = $parts[1] }
Write-Log -Level "INFO" -Message "----------------------------------------"
Write-Log -Level "INFO" -Message "----- 未运行的容器 -----"
foreach ($c in $stoppedContainers) {
Write-Log -Level "INFO" -Message (" [STOPPED] {0} ({1}) - {2}" -f $c.Name, $c.Id, $c.Status)
}
$allIds = ($idNameMap.Keys | ForEach-Object { $_ }) -join ' '
Write-Log -Level "INFO" -Message ("发现容器共 {0} 个" -f $idNameMap.Count)
# 一次性 inspect 所有容器(带 size)
$inspectCmd = "$runtime inspect --size $allIds 2>/dev/null"
$inspectResult = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $inspectCmd
if ($inspectResult.ExitCode -ne 0 -or -not $inspectResult.Output) {
Write-Log -Level "WARN" -Message "无法批量获取容器 inspect 信息"
return $results
$results += @{
Check = "容器信息收集"
Status = "完成"
Details = "运行中: $($runningContainers.Count),未运行: $($stoppedContainers.Count)"
Success = $true
}
try {
$inspectArr = $inspectResult.Output | ConvertFrom-Json
# 确保为数组
if ($inspectArr -isnot [System.Collections.IEnumerable]) { $inspectArr = @($inspectArr) }
} catch {
Write-Log -Level "WARN" -Message "inspect JSON 解析失败"
return $results
# =====================================================================
# Redis 容器异常:日志导出 + 远端修复 + 复检 (需求文档第12点)
# =====================================================================
# 1) Redis 日志路径根据平台判断
$platformType = $Global:PlatformType # 你前面平台识别时应已设置此全局变量:'new' 或 'old'
$redisLogPath = "/var/www/redis/data/redis.log" # 传统平台默认路径
if ($platformType -eq "new") {
# 新统一平台路径(根据文档):/data/middleware/redis/data/redis.log
$redisLogPath = "/data/middleware/redis/data/redis.log"
}
foreach ($info in $inspectArr) {
# 名称和ID
$fullId = if ($info.PSObject.Properties['Id']) { $info.Id } else { $null }
$shortId = if ($fullId) { ($fullId -replace '(.{12}).*', '$1') } else { '' }
$name = $null
if ($fullId) {
$shortKey = $fullId.Substring(0, [Math]::Min(12, $fullId.Length))
if ($idNameMap.ContainsKey($shortKey)) { $name = $idNameMap[$shortKey] }
}
if (-not $name -and $info.PSObject.Properties['Name'] -and $info.Name) { $name = ($info.Name -replace '^/','') }
if (-not $name -and $info.PSObject.Properties['Config'] -and $info.Config -and $info.Config.PSObject.Properties['Hostname']) { $name = $info.Config.Hostname }
if (-not $name) { $name = $shortId }
# 基本信息
$image = $null
if ($info.PSObject.Properties['Config'] -and $info.Config -and $info.Config.PSObject.Properties['Image']) { $image = $info.Config.Image }
$created = if ($info.PSObject.Properties['Created']) { $info.Created } else { $null }
$status = 'unknown'
$running = $false
if ($info.PSObject.Properties['State'] -and $info.State -and $info.State.PSObject.Properties['Status']) {
$status = $info.State.Status
$running = ($status -eq 'running')
}
$health = $null
if ($info.PSObject.Properties['State'] -and $info.State -and $info.State.PSObject.Properties['Health']) {
$healthObj = $info.State.PSObject.Properties['Health'].Value
if ($healthObj -and $healthObj.PSObject.Properties['Status']) { $health = $healthObj.Status }
}
$restartCount = 0
if ($info.PSObject.Properties['RestartCount']) { $restartCount = $info.RestartCount }
$restartPolicy = $null
if ($info.PSObject.Properties['HostConfig'] -and $info.HostConfig -and $info.HostConfig.PSObject.Properties['RestartPolicy']) {
$rpObj = $info.HostConfig.RestartPolicy
if ($rpObj -and $rpObj.PSObject.Properties['Name']) { $restartPolicy = $rpObj.Name }
}
$sizeRw = $null
if ($info.PSObject.Properties['SizeRw']) { $sizeRw = $info.SizeRw }
$sizeRoot = $null
if ($info.PSObject.Properties['SizeRootFs']) { $sizeRoot = $info.SizeRootFs }
# 端口映射(主机端口 -> 容器端口/协议)
$ports = @()
if ($info.PSObject.Properties['NetworkSettings'] -and $info.NetworkSettings -and $info.NetworkSettings.PSObject.Properties['Ports']) {
$portsObj = $info.NetworkSettings.Ports
if ($portsObj -is [System.Collections.IDictionary]) {
foreach ($k in $portsObj.Keys) {
$binding = $portsObj[$k]
if ($binding) {
foreach ($b in $binding) {
$hostIp = if ($b.PSObject.Properties['HostIp'] -and $b.HostIp) { $b.HostIp } else { '0.0.0.0' }
$hostPort = if ($b.PSObject.Properties['HostPort']) { $b.HostPort } else { '' }
$ports += ("{0}:{1}->{2}" -f $hostIp, $hostPort, $k)
# 本地自检结果目录:形如 output\<IP>\logs\redis\
$baseOutputDir = Join-Path -Path $PSScriptRoot -ChildPath "output"
$serverDir = Join-Path -Path $baseOutputDir -ChildPath $Server.IP
$redisOutDir = Join-Path -Path $serverDir -ChildPath "logs\redis"
if (-not (Test-Path $redisOutDir)) {
New-Item -Path $redisOutDir -ItemType Directory -Force | Out-Null
}
$localRedisLog = Join-Path -Path $redisOutDir -ChildPath "redis.log"
Write-Log -Level "INFO" -Message "[Redis] 准备导出 redis 日志: $redisLogPath -> $localRedisLog"
# 2) 从远端导出 redis.log 到本地
# 这里假定你已有一个封装的远程下载函数,例如 Download-RemoteFile
# 如果你实际用的是 Get-SFTPItem 或者其他名字,请替换为你的函数名和参数。
$exportOk = $false
try {
$downloadRes = Download-RemoteFile -Server $Server -RemotePath $redisLogPath -LocalPath $localRedisLog -ErrorAction Stop
if ($downloadRes -and $downloadRes.Success) {
Write-Log -Level "SUCCESS" -Message "[Redis] redis.log 导出成功,已保存到本地: $localRedisLog"
$exportOk = $true
} else {
$ports += ("- -> {0}" -f $k)
Write-Log -Level "WARN" -Message "[Redis] redis.log 导出失败(返回结果不成功),请检查远端文件是否存在:$redisLogPath"
}
} catch {
Write-Log -Level "WARN" -Message "[Redis] redis.log 导出异常:$($_.Exception.Message)"
}
} else {
foreach ($prop in $portsObj.PSObject.Properties) {
$k = $prop.Name
$binding = $prop.Value
if ($binding) {
foreach ($b in $binding) {
$hostIp = if ($b.PSObject.Properties['HostIp'] -and $b.HostIp) { $b.HostIp } else { '0.0.0.0' }
$hostPort = if ($b.PSObject.Properties['HostPort']) { $b.HostPort } else { '' }
$ports += ("{0}:{1}->{2}" -f $hostIp, $hostPort, $k)
$results += @{
Check = "Redis日志导出"
Status = ($exportOk ? "完成" : "失败")
Details = $exportOk ? "redis.log 导出成功 -> $localRedisLog" : "redis.log 导出失败或文件不存在 ($redisLogPath)"
Success = $exportOk
}
} else {
$ports += ("- -> {0}" -f $k)
# 3) Redis 容器异常判定
# 条件:uredis 容器未运行,且没有其他名字中包含 'redis' 的运行中容器
$redisRunning = $runningContainers | Where-Object { $_.Name -match '(?i)redis' }
$uredisRunning = $redisRunning | Where-Object { $_.Name -eq 'uredis' }
$uredisStopped = $stoppedContainers | Where-Object { $_.Name -eq 'uredis' }
$redisNeedRepair = $false
if (-not $uredisRunning -and $uredisStopped) {
if (-not $redisRunning) {
# uredis 存在但未运行,且没有其他 redis 命名的运行中容器
$redisNeedRepair = $true
}
}
if (-not $redisNeedRepair) {
Write-Log -Level "INFO" -Message "[Redis] 未检测到需要自动修复的 Redis 容器异常"
return $results
}
Write-Log -Level "ERROR" -Message "[Redis] 检测到 Redis 容器异常:uredis 未运行,且无其他 redis 命名容器运行,开始执行远端修复"
# 4) 远端修复:上传 issue_handler.sh 并执行 redis_container_exception (非交互模式)
$repairItem = [ordered]@{
Check = "Redis容器修复"
Status = "未执行"
Details = ""
Success = $false
}
# 网络信息(网络名:IP)
$networks = @()
$ipAddr = $null
if ($info.PSObject.Properties['NetworkSettings'] -and $info.NetworkSettings) {
if ($info.NetworkSettings.PSObject.Properties['Networks'] -and $info.NetworkSettings.Networks) {
$netsObj = $info.NetworkSettings.Networks
if ($netsObj -is [System.Collections.IDictionary]) {
foreach ($nk in $netsObj.Keys) {
$val = $netsObj[$nk]
$nip = if ($val -and $val.PSObject.Properties['IPAddress']) { $val.IPAddress } else { $null }
if (-not $ipAddr -and $nip) { $ipAddr = $nip }
$nipOut = if ($nip) { $nip } else { '-' }
$networks += ("{0}:{1}" -f $nk, $nipOut)
try {
$serverForRepair = @{
IP = $Server.IP
User = $Server.User
Pass = $Server.Pass
Port = $Server.Port
}
# Upload_the_repair_script 内部应拼出:
# ./issue_handler.sh --action redis_container_exception --non-interactive --yes
$repairRes = Upload_the_repair_script -Server $serverForRepair -Action "redis_container_exception" -Platform "auto" -RemoteDir "/home/repair_scripts"
if ($repairRes -and $repairRes['Success']) {
Write-Log -Level "SUCCESS" -Message "[Redis] 远端 Redis 容器修复脚本执行成功 (redis_container_exception)"
$repairItem.Status = "已执行"
$repairItem.Details = "远端脚本执行成功 (redis_container_exception)"
$repairItem.Success = $true
# 5) 修复完成后的复检
Write-Log -Level "INFO" -Message "[Redis] 修复后进行 uredis 容器复检..."
$checkCmd = "docker ps --format '{{.Names}}' | grep -w 'uredis' || echo 'NO_UREDIS'"
$recheck = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $checkCmd
if ($recheck.ExitCode -eq 0 -and -not ($recheck.Output -contains 'NO_UREDIS')) {
Write-Log -Level "SUCCESS" -Message "[Redis] Redis容器复检成功:uredis 已处于运行状态"
$repairItem.Details += " | 复检成功:uredis 已运行"
} else {
foreach ($prop in $netsObj.PSObject.Properties) {
$nk = $prop.Name
$val = $prop.Value
$nip = if ($val -and $val.PSObject.Properties['IPAddress']) { $val.IPAddress } else { $null }
if (-not $ipAddr -and $nip) { $ipAddr = $nip }
$nipOut = if ($nip) { $nip } else { '-' }
$networks += ("{0}:{1}" -f $nk, $nipOut)
}
}
Write-Log -Level "WARN" -Message "[Redis] Redis容器复检失败:仍未检测到运行中的 uredis 容器,需要人工排查"
$repairItem.Status = "部分成功"
$repairItem.Details += " | 复检失败:uredis 仍未运行,请人工排查"
}
if (-not $ipAddr -and $info.NetworkSettings.PSObject.Properties['IPAddress'] -and $info.NetworkSettings.IPAddress) { $ipAddr = $info.NetworkSettings.IPAddress }
} else {
$errMsg = "未知错误"
if ($repairRes -is [hashtable]) {
if ($repairRes.ContainsKey('Error') -and $repairRes['Error']) { $errMsg = [string]::Join(' ', $repairRes['Error']) }
elseif ($repairRes.ContainsKey('Output') -and $repairRes['Output']) { $errMsg = [string]::Join(' ', $repairRes['Output']) }
elseif ($repairRes.ContainsKey('Message') -and $repairRes['Message']) { $errMsg = $repairRes['Message'] }
} elseif ($repairRes) {
$errMsg = $repairRes.ToString()
}
# 挂载列表(Source:Destination(:rw/ro))
$mounts = @()
if ($info.PSObject.Properties['Mounts'] -and $info.Mounts) {
foreach ($m in $info.Mounts) {
$src = if ($m.PSObject.Properties['Source']) { $m.Source } else { '' }
$dst = if ($m.PSObject.Properties['Destination']) { $m.Destination } else { '' }
$rw = if ($m.PSObject.Properties['RW'] -and $m.RW) { 'rw' } else { 'ro' }
$mounts += ("{0}:{1}({2})" -f $src, $dst, $rw)
Write-Log -Level "ERROR" -Message "[Redis] 远端 Redis 容器修复执行失败:$errMsg"
$repairItem.Status = "失败"
$repairItem.Details = "远程修复失败:$errMsg"
}
}
catch {
Write-Log -Level "ERROR" -Message "[Redis] 调用 Upload_the_repair_script 异常:$($_.Exception.Message)"
$repairItem.Status = "异常"
$repairItem.Details = "调用修复脚本异常:$($_.Exception.Message)"
}
$item = @{
Name = $name
Id = $shortId
Image = $image
Status = $status
Running = $running
Health = $health
RestartPolicy = $restartPolicy
RestartCount = $restartCount
Created = $created
IPAddress = $ipAddr
Networks = $networks
Ports = $ports
Mounts = $mounts
SizeRw = $sizeRw
SizeRootFs = $sizeRoot
}
$results += $item
# 摘要日志
$icon = if ($running) { '✅' } else { '⛔' }
$portStr = if ($ports.Count -gt 0) { ($ports -join ', ') } else { '-' }
$netStr = if ($networks.Count -gt 0) { ($networks -join ', ') } else { '-' }
$szStrParts = @()
if ($sizeRw -ne $null) { $szStrParts += ("rw={0}" -f $sizeRw) }
if ($sizeRoot -ne $null) { $szStrParts += ("root={0}" -f $sizeRoot) }
$szOut = if ($szStrParts.Count -gt 0) { ($szStrParts -join ', ') } else { '-' }
$rpStr = if ($restartPolicy) { "; 重启策略: $restartPolicy" } else { '' }
$level = if ($running) { 'SUCCESS' } else { 'INFO' }
Write-Log -Level $level -Message "- $icon 名称: $($name) | 镜像: $($image) | 状态: $($status)$rpStr | IP: $($ipAddr)"
Write-Log -Level "INFO" -Message " 端口: $portStr"
Write-Log -Level "INFO" -Message " 网络: $netStr | 大小: $szOut"
if ($mounts.Count -gt 0) {
$showMounts = if ($mounts.Count -gt 3) { ($mounts | Select-Object -First 3) + '...' } else { $mounts }
Write-Log -Level "INFO" -Message (" 挂载: {0}" -f ($showMounts -join '; '))
}
}
Write-Log -Level "INFO" -Message "容器信息收集完成"
$results += $repairItem
return $results
}
......@@ -2874,15 +2871,25 @@ function Upload_the_repair_script {
# 4) 远端执行修复动作
$platArg = if ($Platform -and $Platform.Length -gt 0) { "--platform $Platform" } else { "" }
# 保持原有逻辑,只新增 redis_container_exception 分支
$extraArgs = ""
if ($Action -eq "fix_ntp_config") { $extraArgs = "--ntp-auto" }
elseif ($Action -eq "fix_port_access") { $extraArgs = "--non-interactive --yes" }
if ($Action -eq "fix_ntp_config") {
$extraArgs = "--ntp-auto"
}
elseif ($Action -eq "fix_port_access") {
$extraArgs = "--non-interactive --yes"
}
elseif ($Action -eq "fix_external_service_disconnect") {
# 对外服务修复同样走非交互 + 默认 yes
# 对外服务修复非交互 + 默认 yes
$extraArgs = "--non-interactive --yes"
}
elseif ($Action -eq "fix_dns_config") {
# DNS 修复同样走非交互模式
# DNS 修复:非交互
$extraArgs = "--non-interactive --yes"
}
elseif ($Action -eq "redis_container_exception") {
# Redis 容器异常修复:需求文档第12点,必须非交互 + 默认 yes
$extraArgs = "--non-interactive --yes"
}
......@@ -2900,8 +2907,11 @@ function Upload_the_repair_script {
$errorOut = if ($execRes -is [hashtable] -and $execRes.ContainsKey('Error')) { $execRes['Error'] } else { $null }
$succ = ($exitCode -eq 0)
if ($succ) { Write-Log -Level "SUCCESS" -Message "远端修复执行成功: $Action" }
else { Write-Log -Level "ERROR" -Message "远端修复执行失败,ExitCode=$exitCode" }
if ($succ) {
Write-Log -Level "SUCCESS" -Message "远端修复执行成功: $Action"
} else {
Write-Log -Level "ERROR" -Message "远端修复执行失败,ExitCode=$exitCode"
}
return @{
Success = $succ
......
## 服务自检脚本使用说明
### 1、将整个Server_health_check文件夹拷贝到桌面
### 2、打开电脑的powershell
### 3、切换到Server_health_check文件夹路径
### 4、执行指令
Unblock-File -Path "C:\Users\UBAINS\Desktop\Sever_health_check\check_server_health.ps1"(后面路径替换成自己电脑上的路径!!!)
### 5、执行指令
.\check_server_health.ps1
### 6、步骤说明:
#### 6.1、服务器信息录入
根据提示输入0,再依次输入服务器IP地址、22端口、账号、密码信息即可。
#### 6.2、
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论