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

fix(server-check): 优化防火墙检测与远程文件传输逻辑

- 改进防火墙状态检测逻辑,区分 firewalld 和 iptables 状态
- 新增 Copy-File-To-Remote 函数,支持多种方式上传文件(pscp/plink/scp)
- 重构 Upload_the_repair_script 函数,使用新传输方法并增强容错
- 为修复动作添加非交互参数支持,防止远端执行卡住
- 移除部分冗余日志输出,提升脚本执行效率
- 统一远程命令执行与结果解析方式,提高稳定性
上级 c69afd4d
...@@ -1208,13 +1208,27 @@ function Test-ServerResources { ...@@ -1208,13 +1208,27 @@ function Test-ServerResources {
$firewallActive = $false $firewallActive = $false
$firewallType = "unknown" $firewallType = "unknown"
if ($firewallStatusResult.Output -match 'active') { # 严格匹配 firewalld 的 is-active 输出(active/inactive/failed/unknown)
$statusLine = ($firewallStatusResult.Output | Select-Object -First 1)
if ($statusLine) { $statusLine = $statusLine.Trim().ToLower() } else { $statusLine = "unknown" }
if ($statusLine -eq "active") {
$firewallActive = $true $firewallActive = $true
$firewallType = "firewalld" $firewallType = "firewalld"
} } elseif ($statusLine -eq "inactive" -or $statusLine -eq "failed" -or $statusLine -eq "unknown") {
elseif ($firewallStatusResult.Output -match 'running|OK') { $firewallActive = $false
# 尝试判断 iptables(service iptables status 的首行)
$ipLine = ($firewallStatusResult.Output | Select-Object -Last 1)
if ($ipLine) {
$ipl = $ipLine.Trim().ToLower()
if ($ipl -match '\brunning\b' -or $ipl -match '\bok\b') {
$firewallActive = $true $firewallActive = $true
$firewallType = "iptables" $firewallType = "iptables"
} elseif ($ipl -match 'stopped|not running|inactive|failed') {
$firewallActive = $false
$firewallType = "iptables"
}
}
} }
$openPorts = @() $openPorts = @()
...@@ -1266,7 +1280,7 @@ function Test-ServerResources { ...@@ -1266,7 +1280,7 @@ function Test-ServerResources {
$serverForRepair = @{ IP = $Server.IP; User = $Server.User; Pass = $Server.Pass; Port = $Server.Port } $serverForRepair = @{ IP = $Server.IP; User = $Server.User; Pass = $Server.Pass; Port = $Server.Port }
# 触发远端修复:修复端口开放/防火墙配置 # 触发远端修复:修复端口开放/防火墙配置
Write-Log -Level "INFO" -Message "[FIREWALL] 触发远端修复: ./issue_handler.sh --action fix_port_access --platform auto --non-interactive" Write-Log -Level "INFO" -Message "[FIREWALL] 触发远端修复: ./issue_handler.sh --action fix_port_access --platform auto --non-interactive"
$fwRepairRes = Upload_the_repair_script -Server $serverForRepair -Action "fix_port_access" -Platform "auto" -RemoteDir "/home/repair_scripts" $fwRepairRes = Upload_the_repair_script -Server $serverForRepair -Action "fix_port_access" -Platform "auto" -RemoteDir "/home/repair_scripts" # 非交互在函数内拼接
if ($fwRepairRes -and $fwRepairRes['Success']) { if ($fwRepairRes -and $fwRepairRes['Success']) {
Write-Log -Level "SUCCESS" -Message "[FIREWALL] 远端修复已执行成功 (fix_port_access)" Write-Log -Level "SUCCESS" -Message "[FIREWALL] 远端修复已执行成功 (fix_port_access)"
# 修复后复检防火墙状态与开放端口 # 修复后复检防火墙状态与开放端口
...@@ -2509,148 +2523,160 @@ function Check-FilePermissions { ...@@ -2509,148 +2523,160 @@ function Check-FilePermissions {
return @{ Summary = $summaryText; Lines = $lines } return @{ Summary = $summaryText; Lines = $lines }
} }
# ================================ # ================================
# 上传修复脚本函数 # 远程复制辅助函数(pscp 优先)
# ================================ # ================================
function Upload_the_repair_script { function Copy-File-To-Remote {
param( param(
[Parameter(Mandatory = $true)] [hashtable]$Server, [Parameter(Mandatory=$true)] [string]$LocalPath,
[Parameter(Mandatory = $true)] [string]$Action, [Parameter(Mandatory=$true)] [hashtable]$Server,
[Parameter(Mandatory = $false)] [ValidateSet('auto','new','old')] [string]$Platform = 'auto', [Parameter(Mandatory=$true)] [string]$RemoteDir
[Parameter(Mandatory = $false)] [string]$RemoteDir = "/home/repair_scripts",
[Parameter(Mandatory = $false)] [string]$LocalIssueHandlerPath
) )
if (-not (Test-Path -LiteralPath $LocalPath)) {
Write-Log -Level "ERROR" -Message "本地文件不存在: $LocalPath"
return $false
}
Write-Host "" # 1) 用 pscp.exe 直接传输
Write-Log -Level "INFO" -Message "========== 上传修复脚本并执行 ==========" if ($script:PSCP_PATH -and (Test-Path $script:PSCP_PATH)) {
Write-Log -Level "INFO" -Message "目标: $($Server.User)@$($Server.IP):$($Server.Port) | 动作: $Action | 平台: $Platform" Write-Log -Level "INFO" -Message ("已找到 pscp: {0}" -f $script:PSCP_PATH)
$pscpArgs = @(
# 1) 定位 pscp "-P", $Server.Port,
$pscpPath = $script:PSCP_PATH "-l", $Server.User,
if (-not $pscpPath -or -not (Test-Path $pscpPath)) { "-pw", $Server.Pass,
$cmdInPath = Get-Command pscp -ErrorAction SilentlyContinue "-batch",
if ($cmdInPath) { $pscpPath = $cmdInPath.Source } $LocalPath,
("{0}@{1}:{2}/" -f $Server.User, $Server.IP, $RemoteDir)
)
try {
$out = & $script:PSCP_PATH @pscpArgs 2>&1
$code = $LASTEXITCODE
if ($code -ne 0 -and ($out -match "host key" -or $out -match "Cannot confirm")) {
$cmdLine = "echo y | `"$($script:PSCP_PATH)`" -P $($Server.Port) -l $($Server.User) -pw `"$($Server.Pass)`" `"$LocalPath`" `"$($Server.User)@$($Server.IP):$RemoteDir/`""
$out = cmd /c $cmdLine 2>&1
$code = $LASTEXITCODE
}
if ($code -eq 0) {
Write-Log -Level "SUCCESS" -Message "文件上传成功: $LocalPath -> $($Server.User)@$($Server.IP):$RemoteDir/"
return $true
} else {
Write-Log -Level "ERROR" -Message "pscp 上传失败: $out"
return $false
} }
if (-not $pscpPath -or -not (Test-Path $pscpPath)) { } catch {
Write-Log -Level "ERROR" -Message "pscp.exe 未找到,无法上传脚本" Write-Log -Level "ERROR" -Message "pscp 异常: $($_.Exception.Message)"
Write-Log -Level "ERROR" -Message "请将 pscp.exe 放在脚本同目录,或加入 PATH。下载: https://the.earth.li/~sgtatham/putty/latest/w64/pscp.exe" return $false
return @{
Success = $false
Step = "CheckPSCP"
Message = "pscp.exe not found"
} }
} }
Write-Log -Level "INFO" -Message "已找到 pscp: $pscpPath"
# 2) 定位本地 issue_handler.sh # 2) 没有 pscp 时,使用 plink + base64 方式传输(兼容)
if (-not $LocalIssueHandlerPath) { if ($script:PLINK_PATH -and (Test-Path $script:PLINK_PATH)) {
$candidates = @( $fileName = [System.IO.Path]::GetFileName($LocalPath)
(Join-Path $SCRIPT_DIR "issue_handler.sh"), $remoteFile = "$RemoteDir/$fileName"
(Join-Path (Split-Path $SCRIPT_DIR -Parent) "常见问题处理\issue_handler.sh"), Write-Log -Level "INFO" -Message "使用 plink/base64 传输: $fileName"
(Join-Path (Split-Path (Split-Path $SCRIPT_DIR -Parent) -Parent) "辅助工具\脚本工具\常见问题处理\issue_handler.sh")
) | Select-Object -Unique $bytes = [System.IO.File]::ReadAllBytes($LocalPath)
$LocalIssueHandlerPath = ($candidates | Where-Object { Test-Path $_ } | Select-Object -First 1) $b64 = [System.Convert]::ToBase64String($bytes)
# 远端接收命令:创建目录、写入、解码
$recvCmd = @"
set -e
mkdir -p '$RemoteDir'
cat > /tmp/.upload_${fileName}.b64 <<'__EOF__'
$b64
__EOF__
base64 -d /tmp/.upload_${fileName}.b64 > '$remoteFile'
rm -f /tmp/.upload_${fileName}.b64
"@
$plinkArgs = @("-ssh","-P",$Server.Port,"-l",$Server.User,"-pw",$Server.Pass,"-batch",$Server.IP,$recvCmd)
$out = & $script:PLINK_PATH @plinkArgs 2>&1
$code = $LASTEXITCODE
if ($code -eq 0) {
Write-Log -Level "SUCCESS" -Message "文件上传成功: $LocalPath -> $remoteFile"
return $true
} else {
Write-Log -Level "ERROR" -Message "plink/base64 上传失败: $out"
return $false
}
} }
if (-not $LocalIssueHandlerPath -or -not (Test-Path $LocalIssueHandlerPath)) { # 3) sshpass + scp(Linux/WSL 环境下)
Write-Log -Level "ERROR" -Message "未找到本地 issue_handler.sh" try {
Write-Log -Level "ERROR" -Message "请确认脚本存在,或通过 -LocalIssueHandlerPath 指定路径" $scpCmd = "sshpass -p `"$($Server.Pass)`" scp -o StrictHostKeyChecking=no -P $($Server.Port) `"$LocalPath`" $($Server.User)@$($Server.IP):`"$RemoteDir/`""
return @{ $out = & powershell -NoProfile -Command $scpCmd
Success = $false if ($LASTEXITCODE -eq 0) {
Step = "FindLocalScript" Write-Log -Level "SUCCESS" -Message "文件上传成功 (sshpass/scp)"
Message = "Local issue_handler.sh not found" return $true
} else {
Write-Log -Level "ERROR" -Message "sshpass/scp 上传失败: $out"
return $false
} }
} catch {
Write-Log -Level "ERROR" -Message "未找到可用的传输工具 (pscp/plink/sshpass)"
return $false
} }
Write-Log -Level "INFO" -Message "本地脚本: $LocalIssueHandlerPath" }
# ================================
# 上传修复脚本函数
# ================================
function Upload_the_repair_script {
param(
[hashtable]$Server,
[string]$Action,
[string]$Platform = "auto",
[string]$RemoteDir = "/home/repair_scripts"
)
Write-Log -Level "INFO" -Message "========== 上传修复脚本并执行 =========="
Write-Log -Level "INFO" -Message "目标: $($Server.User)@$($Server.IP):$($Server.Port) | 动作: $Action | 平台: $Platform"
# 3) 远端准备目录 # 1) 确保远端目录存在
$prepCmd = "mkdir -p '$RemoteDir'" $prepCmd = "mkdir -p '$RemoteDir'"
$prepRes = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $prepCmd $prepRes = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $prepCmd
$prepExit = if ($prepRes -is [hashtable] -and $prepRes.ContainsKey('ExitCode')) { [int]$prepRes['ExitCode'] } else { -1 } $prepExit = if ($prepRes -is [hashtable] -and $prepRes.ContainsKey('ExitCode')) { [int]$prepRes['ExitCode'] } else { -1 }
if ($prepExit -ne 0) { if ($prepExit -ne 0) {
$prepOut = if ($prepRes -is [hashtable] -and $prepRes.ContainsKey('Output')) { $prepRes['Output'] } else { $null } $prepOut = if ($prepRes -is [hashtable] -and $prepRes.ContainsKey('Output')) { $prepRes['Output'] } else { $null }
$prepErr = if ($prepRes -is [hashtable] -and $prepRes.ContainsKey('Error')) { $prepRes['Error'] } else { $null } $prepErr = if ($prepRes -is [hashtable] -and $prepRes.ContainsKey('Error')) { $prepRes['Error'] } else { $null }
Write-Log -Level "ERROR" -Message "远端目录创建失败: $RemoteDir" return @{ Success = $false; Step = "MkdirRemote"; ExitCode = $prepExit; Output = $prepOut; Error = $prepErr }
return @{
Success = $false
Step = "MkdirRemote"
ExitCode= $prepExit
Output = $prepOut
Error = $prepErr
}
} }
Write-Log -Level "INFO" -Message "远端目录已就绪: $RemoteDir"
# 4) 上传脚本 # 2) 上传 issue_handler.sh 到远端目录
$remoteTarget = "$($Server.User)@$($Server.IP):$RemoteDir/" $localScript = Join-Path (Split-Path -Parent $PSCommandPath) "issue_handler.sh"
Write-Log -Level "INFO" -Message "开始上传 -> $remoteTarget" Write-Log -Level "INFO" -Message "本地脚本: $localScript"
$pscpArgs = @( $scpOk = Copy-File-To-Remote -LocalPath $localScript -Server $Server -RemoteDir $RemoteDir
"-P", "$($Server.Port)", if (-not $scpOk) {
"-pw", "$($Server.Pass)", return @{ Success = $false; Step = "UploadScript"; Error = "SCP 上传失败" }
"$LocalIssueHandlerPath",
$remoteTarget
)
try {
$null = & "$pscpPath" @pscpArgs
} catch {
Write-Log -Level "ERROR" -Message "pscp 执行异常: $($_.Exception.Message)"
return @{
Success = $false
Step = "Upload"
Message = $_.Exception.Message
}
} }
Write-Log -Level "SUCCESS" -Message "脚本上传完成" Write-Log -Level "SUCCESS" -Message "脚本上传完成"
# 5) 远端修复换行符并赋权
$remoteFile = "$RemoteDir/issue_handler.sh" $remoteFile = "$RemoteDir/issue_handler.sh"
$fixCmd = @( Write-Log -Level "INFO" -Message "远端脚本就绪: $remoteFile"
"set -e",
"chmod +x '$remoteFile' || true", # 3) 修复换行并赋权
"if command -v dos2unix >/dev/null 2>&1; then dos2unix '$remoteFile' || true; else sed -i 's/\r$//' '$remoteFile' || true; fi" $fixCmd = "set -e && cd '$RemoteDir' && dos2unix '$remoteFile' 2>/dev/null || true && chmod +x '$remoteFile'"
) -join " && "
$fixRes = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $fixCmd $fixRes = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $fixCmd
$fixExit = if ($fixRes -is [hashtable] -and $fixRes.ContainsKey('ExitCode')) { [int]$fixRes['ExitCode'] } else { -1 } $fixExit = if ($fixRes -is [hashtable] -and $fixRes.ContainsKey('ExitCode')) { [int]$fixRes['ExitCode'] } else { -1 }
if ($fixExit -ne 0) { if ($fixExit -ne 0) {
$fixOut = if ($fixRes -is [hashtable] -and $fixRes.ContainsKey('Output')) { $fixRes['Output'] } else { $null } $fixOut = if ($fixRes -is [hashtable] -and $fixRes.ContainsKey('Output')) { $fixRes['Output'] } else { $null }
$fixErr = if ($fixRes -is [hashtable] -and $fixRes.ContainsKey('Error')) { $fixRes['Error'] } else { $null } $fixErr = if ($fixRes -is [hashtable] -and $fixRes.ContainsKey('Error')) { $fixRes['Error'] } else { $null }
Write-Log -Level "ERROR" -Message "远端脚本准备失败 (chmod/dos2unix)" return @{ Success = $false; Step = "PrepareRemoteScript"; ExitCode = $fixExit; Output = $fixOut; Error = $fixErr }
return @{
Success = $false
Step = "PrepareRemoteScript"
ExitCode= $fixExit
Output = $fixOut
Error = $fixErr
} }
}
Write-Log -Level "INFO" -Message "远端脚本就绪: $remoteFile"
# 6) 远端执行修复动作 # 4) 远端执行修复动作
$platArg = if ($Platform -and $Platform.Length -gt 0) { "--platform $Platform" } else { "" } $platArg = if ($Platform -and $Platform.Length -gt 0) { "--platform $Platform" } else { "" }
$extraArgs = "" $extraArgs = ""
if ($Action -eq "fix_ntp_config") { if ($Action -eq "fix_ntp_config") { $extraArgs = "--ntp-auto" }
# 对 NTP 修复追加无交互参数,避免远端卡住 elseif ($Action -eq "fix_port_access") { $extraArgs = "--non-interactive --yes" }
$extraArgs = "--ntp-auto"
} $execCmd = @("set -e","cd '$RemoteDir'","./issue_handler.sh --action $Action $platArg $extraArgs") -join " && "
$execCmd = @(
"set -e",
"cd '$RemoteDir'",
"./issue_handler.sh --action $Action $platArg $extraArgs"
) -join " && "
Write-Log -Level "INFO" -Message "开始执行远端修复: $execCmd" Write-Log -Level "INFO" -Message "开始执行远端修复: $execCmd"
$execRes = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $execCmd $execRes = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $execCmd
$exitCode = if ($execRes -is [hashtable] -and $execRes.ContainsKey('ExitCode')) { [int]$execRes['ExitCode'] } else { -1 } $exitCode = if ($execRes -is [hashtable] -and $execRes.ContainsKey('ExitCode')) { [int]$execRes['ExitCode'] } else { -1 }
$output = if ($execRes -is [hashtable] -and $execRes.ContainsKey('Output')) { $execRes['Output'] } else { $null } $output = if ($execRes -is [hashtable] -and $execRes.ContainsKey('Output')) { $execRes['Output'] } else { $null }
$errorOut = if ($execRes -is [hashtable] -and $execRes.ContainsKey('Error')) { $execRes['Error'] } else { $null } $errorOut = if ($execRes -is [hashtable] -and $execRes.ContainsKey('Error')) { $execRes['Error'] } else { $null }
$succ = ($exitCode -eq 0) $succ = ($exitCode -eq 0)
if ($succ) { if ($succ) { Write-Log -Level "SUCCESS" -Message "远端修复执行成功: $Action" }
Write-Log -Level "SUCCESS" -Message "远端修复执行成功: $Action" else { Write-Log -Level "ERROR" -Message "远端修复执行失败,ExitCode=$exitCode" }
} else {
Write-Log -Level "ERROR" -Message "远端修复执行失败,ExitCode=$exitCode"
}
return @{ return @{
Success = $succ Success = $succ
...@@ -2663,7 +2689,6 @@ function Upload_the_repair_script { ...@@ -2663,7 +2689,6 @@ function Upload_the_repair_script {
Error = $errorOut Error = $errorOut
} }
} }
# ================================ # ================================
# 检测 DataBakup 服务 # 检测 DataBakup 服务
# ================================ # ================================
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论