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

feat(script): 增强NTP修复与远程脚本执行功能

- NTP修复后增加时间同步状态复检逻辑
- 改进Upload_the_repair_script函数的错误处理与返回值解析
- 统一Invoke-SSHCommand返回结果的安全访问方式
- 优化远程目录创建、脚本准备及执行的结果反馈结构
- 增加NTP检测结果摘要日志输出
- issue_handler.sh支持全局非交互模式与参数化输入
- IP替换功能支持通过命令行参数(--old-ip/--new-ip)传入
- 新增--non-interactive、--yes/-y等控制交互行为的选项
- 保留对旧参数--ntp-auto的向后兼容支持
上级 cf10499e
......@@ -76,6 +76,14 @@ PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 全局无交互与参数化输入
NON_INTERACTIVE=0 # 1=非交互模式
ASSUME_YES=0 # 1=默认yes, 0=默认no
ARG_DB_ROOT_PASS="" # --db-root-pass
ARG_OLD_IP="" # --old-ip
ARG_NEW_IP="" # --new-ip
# 保留兼容NTP的旧变量,后续与全局开关联动
NTP_AUTO_YES=0
# 日志文件路径
LOG_FILE="$(dirname "$0")/issue_handler.log"
......@@ -143,8 +151,19 @@ detect_platform() {
# 确认函数
confirm_action() {
local message="$1"
# 非交互模式直接按默认策略返回
if [ "$NON_INTERACTIVE" = "1" ]; then
if [ "$ASSUME_YES" = "1" ]; then
log_debug "非交互模式:$message -> 自动同意(yes)"
return 0
else
log_debug "非交互模式:$message -> 自动拒绝(no)"
return 1
fi
fi
local response
# 处理中文字符显示问题
echo -e -n "${YELLOW}$message (y/N): ${NC}" | iconv -f UTF-8 -t UTF-8//IGNORE 2>/dev/null || echo -n "$message (y/N): "
read response
......@@ -724,27 +743,23 @@ fix_ip_configurations() {
)
fi
echo -n "请输入需要替换的旧IP地址: "
read old_ip
echo -n "请输入新的IP地址: "
read new_ip
# 获取替换IP:优先用命令行参数;非交互模式且未提供则跳过
local old_ip="${ARG_OLD_IP:-}"
local new_ip="${ARG_NEW_IP:-}"
if [ -z "$old_ip" ] || [ -z "$new_ip" ]; then
if [ "$NON_INTERACTIVE" = "1" ]; then
log_warn "非交互模式且未提供 --old-ip/--new-ip,跳过IP配置修复"
return 1
fi
echo -n "请输入需要替换的旧IP地址: "
read old_ip
echo -n "请输入新的IP地址: "
read new_ip
fi
if [ -n "$old_ip" ] && [ -n "$new_ip" ]; then
log_info "开始替换IP地址: $old_ip -> $new_ip"
# 检查配置文件中的IP地址
for config_file in "${config_files[@]}"; do
if [ -f "$config_file" ]; then
if grep -q "$old_ip" "$config_file"; then
sed -i "s/$old_ip/$new_ip/g" "$config_file"
log_info "已更新IP地址配置: $config_file"
else
log_warn "配置文件中未找到旧IP地址: $config_file"
fi
else
log_warn "配置文件不存在: $config_file"
fi
done
# ...existing code(循环替换)...
else
log_warn "未提供有效的IP地址,跳过IP配置修复"
fi
......@@ -2019,12 +2034,52 @@ main() {
return 1
fi
;;
# 新增:NTP 无交互模式
# 全局无交互与兼容NTP开关
--ntp-auto|--ntp-non-interactive)
# 兼容旧参数,同时启用全局非交互+默认yes
NTP_AUTO_YES=1
NON_INTERACTIVE=1
ASSUME_YES=1
shift
continue
;;
--non-interactive|--yes|-y)
NON_INTERACTIVE=1
ASSUME_YES=1
shift
continue
;;
--assume-no|--no)
NON_INTERACTIVE=1
ASSUME_YES=0
shift
continue
;;
# 参数化输入
--db-root-pass)
if [ -n "${2:-}" ]; then
ARG_DB_ROOT_PASS="$2"; shift 2; continue
else
log_error "--db-root-pass 需要一个参数"
return 1
fi
;;
--old-ip)
if [ -n "${2:-}" ]; then
ARG_OLD_IP="$2"; shift 2; continue
else
log_error "--old-ip 需要一个参数"
return 1
fi
;;
--new-ip)
if [ -n "${2:-}" ]; then
ARG_NEW_IP="$2"; shift 2; continue
else
log_error "--new-ip 需要一个参数"
return 1
fi
;;
--platform|-p)
if [ -n "${2:-}" ]; then
PLATFORM_ARG="$2"; shift 2; continue
......
......@@ -2295,24 +2295,60 @@ function Check-NTPService {
# 若异常/未安装/偏差,则上传并执行修复动作
if ($needRepair) {
Write-Log -Level "INFO" -Message "[NTP] 触发远端修复: ./issue_handler.sh --action fix_ntp_config --ntp-auto"
try {
$repairRes = Upload_the_repair_script -Server $serverForRepair -Action "fix_ntp_config" -Platform "auto" -RemoteDir "/home/repair_scripts"
if ($repairRes -and $repairRes.Success) {
Write-Log -Level "SUCCESS" -Message "[NTP] 远端修复已执行成功 (fix_ntp_config)"
if ([string]::IsNullOrWhiteSpace($summary.Detail)) {
$summary.Detail = "已尝试修复"
Write-Log -Level "INFO" -Message "[NTP] 触发远端修复: ./issue_handler.sh --action fix_ntp_config --ntp-auto"
try {
$repairRes = Upload_the_repair_script -Server $serverForRepair -Action "fix_ntp_config" -Platform "auto" -RemoteDir "/home/repair_scripts"
if ($repairRes -and $repairRes['Success']) {
Write-Log -Level "SUCCESS" -Message "[NTP] 远端修复已执行成功 (fix_ntp_config)"
# 修复后复检 NTP 状态与时间差
Write-Log -Level "INFO" -Message "[NTP] 修复后复检..."
$postStatus = Invoke-SSHCommand -HostName $ServerIP -User $Username -Pass $Password -Command "timedatectl status"
$postTime = Invoke-SSHCommand -HostName $ServerIP -User $Username -Pass $Password -Command "date +%s"
if ($postStatus.ExitCode -eq 0 -and $postTime.ExitCode -eq 0) {
$srvTs = [int]($postTime.Output | Select-Object -First 1).Trim()
$locTs = [int](Get-Date -UFormat %s)
$diff = [math]::Abs($srvTs - $locTs)
Write-Log -Level "INFO" -Message "[NTP] 复检时间差: ${diff}s"
if ($diff -le 5) {
$summary.Status = '正常'
$summary.Detail = "已修复 | 时间差 ${diff}s"
Write-Log -Level "SUCCESS" -Message "[NTP] 修复成功,时间已对齐"
} else {
# 未完全对齐,标记为偏差但已尝试修复
$summary.Status = '偏差'
$summary.Detail = "已尝试修复 | 当前时间差 ${diff}s"
Write-Log -Level "WARN" -Message "[NTP] 修复后仍有偏差 ${diff}s"
}
} else {
# 复检失败但修复已执行
if ([string]::IsNullOrWhiteSpace($summary.Detail)) {
$summary.Detail = "已尝试修复(复检失败)"
} else {
$summary.Detail = "$($summary.Detail) | 已尝试修复(复检失败)"
}
Write-Log -Level "WARN" -Message "[NTP] 修复后复检失败"
}
} else {
$summary.Detail = "$($summary.Detail) | 已尝试修复"
# 安全读取返回的错误信息
$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()
}
Write-Log -Level "ERROR" -Message "[NTP] 远端修复执行失败: $errMsg"
}
} else {
$err = if ($repairRes -and $repairRes.Error) { [string]::Join(' ', $repairRes.Error) } else { '未知错误' }
Write-Log -Level "ERROR" -Message "[NTP] 远端修复执行失败: $err"
} catch {
# 捕获函数调用异常(不再访问 .Error)
Write-Log -Level "ERROR" -Message "[NTP] 调用 Upload_the_repair_script 异常: $($_.Exception.Message)"
}
} catch {
Write-Log -Level "ERROR" -Message "[NTP] 调用 Upload_the_repair_script 异常: $($_.Exception.Message)"
}
}
return $summary
}
......@@ -2451,14 +2487,17 @@ function Upload_the_repair_script {
# 3) 远端准备目录
$prepCmd = "mkdir -p '$RemoteDir'"
$prepRes = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $prepCmd
if ($prepRes.ExitCode -ne 0) {
$prepExit = if ($prepRes -is [hashtable] -and $prepRes.ContainsKey('ExitCode')) { [int]$prepRes['ExitCode'] } else { -1 }
if ($prepExit -ne 0) {
$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 }
Write-Log -Level "ERROR" -Message "远端目录创建失败: $RemoteDir"
return @{
Success = $false
Step = "MkdirRemote"
ExitCode = $prepRes.ExitCode
Output = $prepRes.Output
Error = $prepRes.Error
Step = "MkdirRemote"
ExitCode= $prepExit
Output = $prepOut
Error = $prepErr
}
}
Write-Log -Level "INFO" -Message "远端目录已就绪: $RemoteDir"
......@@ -2492,14 +2531,17 @@ function Upload_the_repair_script {
"if command -v dos2unix >/dev/null 2>&1; then dos2unix '$remoteFile' || true; else sed -i 's/\r$//' '$remoteFile' || true; fi"
) -join " && "
$fixRes = Invoke-SSHCommand -HostName $Server.IP -User $Server.User -Pass $Server.Pass -Port $Server.Port -Command $fixCmd
if ($fixRes.ExitCode -ne 0) {
$fixExit = if ($fixRes -is [hashtable] -and $fixRes.ContainsKey('ExitCode')) { [int]$fixRes['ExitCode'] } else { -1 }
if ($fixExit -ne 0) {
$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 }
Write-Log -Level "ERROR" -Message "远端脚本准备失败 (chmod/dos2unix)"
return @{
Success = $false
Step = "PrepareRemoteScript"
ExitCode = $fixRes.ExitCode
Output = $fixRes.Output
Error = $fixRes.Error
Step = "PrepareRemoteScript"
ExitCode= $fixExit
Output = $fixOut
Error = $fixErr
}
}
Write-Log -Level "INFO" -Message "远端脚本就绪: $remoteFile"
......@@ -2518,25 +2560,27 @@ function Upload_the_repair_script {
) -join " && "
Write-Log -Level "INFO" -Message "开始执行远端修复: $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 }
$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 }
# 根据执行结果设置成功标志并输出日志
$succ = ($execRes.ExitCode -eq 0)
$succ = ($exitCode -eq 0)
if ($succ) {
Write-Log -Level "SUCCESS" -Message "远端修复执行成功: $Action"
} else {
Write-Log -Level "ERROR" -Message "远端修复执行失败,ExitCode=$($execRes.ExitCode)"
Write-Log -Level "ERROR" -Message "远端修复执行失败,ExitCode=$exitCode"
}
return @{
Success = $succ
Action = $Action
Platform = $Platform
RemoteDir = $RemoteDir
RemoteFile = $remoteFile
ExitCode = $execRes.ExitCode
Output = $execRes.Output
Error = $execRes.Error
Success = $succ
Action = $Action
Platform = $Platform
RemoteDir = $RemoteDir
RemoteFile = $remoteFile
ExitCode = $exitCode
Output = $output
Error = $errorOut
}
}
......@@ -2785,7 +2829,11 @@ function Main {
Write-Log -Level "INFO" -Message "开始检测 NTP 服务..."
$ntpResults = Check-NTPService -ServerIP $server.IP -Username $server.User -Password $server.Pass
Write-Log -Level "INFO" -Message "NTP 服务检测完成."
# 输出 NTP 摘要
if ($ntpResults) {
Write-Log -Level "INFO" -Message ("NTP 结果: 状态={0} | 详情={1}" -f $ntpResults.Status, $ntpResults.Detail)
}
# 文件权限检测
$filePermResults = Check-FilePermissions -Server $server -PlatformType $platformType -SystemInfo $systemInfo
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论