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

docs(PRD): 更新远程自动化部署需求文档,增加约束描述。

上级 c5d81db5
#!/bin/bash
# 自动化部署包装脚本 - 自动应答所有交互式提示
# 解决whiptail终端问题,提供所有自动应答
#
# 使用方式:
# 1. 上传本脚本到服务器 /data/offline_auto_unifiedPlatform/
# 2. 赋权:chmod +x auto_deploy_wrapper.sh
# 3. 执行:./auto_deploy_wrapper.sh
#
# 原理:
# - TERM=dumb 使whiptail无法渲染,自动回退到默认值(如默认IP)
# - 通过管道预输入所有y/n应答
# - new_auto.sh --all 跳过系统选择菜单,默认部署所有系统
#
# 应答顺序说明(根据new_auto.sh交互流程):
# y - 是否继续执行脚本
# y - 确认网口信息是否正确
# y - 确认日期时间
# y - 确认服务器IP(whiptail回退后仍需应答)
# y - 确认系统类型
# y - 确认部署参数
# y - 确认开始部署
# n - 无企业NTP服务器
export TERM=dumb
cd /data/offline_auto_unifiedPlatform
echo "======== 开始自动化部署 ========"
echo "时间: $(date)"
echo "TERM=$TERM (禁用whiptail交互对话框)"
# 检查部署脚本是否存在
if [ ! -f "./new_auto.sh" ]; then
echo "[错误] 未找到 ./new_auto.sh,请确认部署目录正确"
exit 1
fi
# 使用yes自动应答,配合管道输入
# 应答顺序:y(继续执行) y(网口确认) y(日期确认) y(IP确认) y(系统类型) y(部署参数) y(开始部署) n(无企业NTP)
printf 'y\ny\ny\ny\ny\ny\ny\nn\n' | ./new_auto.sh --all
EXIT_CODE=$?
echo ""
echo "======== 部署脚本执行完毕 ========"
echo "退出码: $EXIT_CODE"
echo "时间: $(date)"
exit $EXIT_CODE
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
自动化部署交互式脚本
使用paramiko处理new_auto.sh --all的交互式部署
通过TERM=dumb禁用whiptail,用管道输入预定义应答
"""
import paramiko
import time
import sys
import re
import os
from datetime import datetime
# 服务器配置
HOST = "192.168.5.52"
PORT = 22
USERNAME = "root"
PASSWORD = "Ubains@123"
# 部署应答序列(与auto_deploy_wrapper.sh一致)
# y(继续执行) y(网口确认) y(日期确认) y(IP确认) y(系统类型) y(部署参数) y(开始部署) n(无企业NTP)
DEPLOY_ANSWERS = "y\ny\ny\ny\ny\ny\ny\nn\n"
# 日志文件
LOG_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "reports")
os.makedirs(LOG_DIR, exist_ok=True)
LOG_FILE = os.path.join(LOG_DIR, f"deploy_log_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt")
class InteractiveDeploy:
def __init__(self):
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.shell = None
self.log_file = None
self.start_time = None
self.output_buffer = ""
def connect(self):
"""连接服务器"""
print(f"[*] 连接服务器 {HOST}:{PORT}...")
self.ssh.connect(HOST, PORT, USERNAME, PASSWORD, timeout=30)
self.shell = self.ssh.invoke_shell(term='xterm', width=200, height=50)
self.shell.settimeout(10)
time.sleep(2)
# 清空连接输出
if self.shell.recv_ready():
self.shell.recv(4096)
print("[+] 服务器连接成功")
def send_command(self, cmd, wait=2):
"""发送命令"""
self.shell.send(cmd + "\n")
time.sleep(wait)
def read_output(self, timeout=30):
"""读取输出"""
output = ""
end_time = time.time() + timeout
while time.time() < end_time:
if self.shell.recv_ready():
try:
chunk = self.shell.recv(4096).decode('utf-8', errors='replace')
output += chunk
if self.log_file:
self.log_file.write(chunk)
self.log_file.flush()
clean = re.sub(r'\x1b\[[0-9;]*[mGKHJ]', '', chunk)
if clean.strip():
print(clean, end='', flush=True)
except Exception:
pass
else:
time.sleep(0.5)
self.output_buffer += output
return output
def handle_deployment(self):
"""处理部署 - 使用TERM=dumb + 管道输入方式"""
self.start_time = datetime.now()
self.log_file = open(LOG_FILE, 'w', encoding='utf-8')
try:
self.connect()
# 进入部署目录
print("[*] 进入部署目录...")
self.send_command("cd /data/offline_auto_unifiedPlatform")
self.read_output(2)
# 检查部署脚本是否存在
print("[*] 检查部署脚本...")
self.send_command("ls -la new_auto.sh")
output = self.read_output(3)
if "No such file" in output:
print("[-] 错误:未找到 new_auto.sh")
return
# 使用TERM=dumb + 管道输入方式执行部署
# 这种方式比逐行匹配交互更可靠
print("[*] 启动部署脚本(TERM=dumb + 管道输入)...")
deploy_cmd = f'export TERM=dumb && printf \'{DEPLOY_ANSWERS}\' | ./new_auto.sh --all'
self.shell.send(deploy_cmd + "\n")
# 持续读取输出,等待部署完成
# 部署通常需要20-30分钟
print("[*] 等待部署完成(预计20-30分钟)...")
self.read_output(timeout=3600)
# 执行 source /etc/profile
print("\n[*] 执行 source /etc/profile ...")
self.send_command("source /etc/profile", wait=2)
self.read_output(3)
# 检查docker容器状态
print("[*] 检查Docker容器状态...")
self.send_command("docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'")
output = self.read_output(5)
print(output)
# 检查对外服务接口
print("[*] 检查对外服务接口...")
self.send_command("curl -sk https://192.168.5.52/exapi/message/getMsgPageList")
output = self.read_output(10)
print(output)
end_time = datetime.now()
duration = end_time - self.start_time
print(f"\n[+] 部署总用时: {duration}")
except Exception as e:
print(f"[-] 部署异常: {e}")
import traceback
traceback.print_exc()
finally:
if self.log_file:
self.log_file.close()
self.ssh.close()
print(f"[*] 日志已保存到: {LOG_FILE}")
if __name__ == "__main__":
deploy = InteractiveDeploy()
deploy.handle_deployment()
......@@ -171,3 +171,19 @@
4. 部署过程中无异常日志输出。
5. 部署脚本日志打印清晰明了。
6. 多个维度来分析。
## 部署注意事项
### SSH远程执行部署脚本
- `new_auto.sh` 内部使用了 `whiptail` 组件进行交互式对话框(如服务器IP确认),在非交互式SSH会话中 `whiptail` 无法正常渲染,会导致脚本卡住。
- 解决方案:执行部署脚本前先设置环境变量 `export TERM=dumb`,使 `whiptail` 自动回退,脚本将使用默认值(如通过 `hostname -I` 获取的默认IP)继续执行。
- 辅助脚本路径:`AuxiliaryTool/ScriptTool/RemoteDeploy/auto_deploy_wrapper.sh`,该脚本封装了 `TERM=dumb` 设置和自动应答管道输入,可直接上传到服务器使用。
### 维护平台(Web界面)操作
- 维护平台中每次敏感操作(下载激活文件、上传授权文件、重启服务)都会弹出"校验身份"对话框,需要重新输入密码和验证码。
- 验证码固定为:`csba`
- 超管账号密码:`superadmin` / `Ubains@1357`
### 服务重启后验证
- 服务重启后(运维系统、预定系统2.0),等待约10分钟让服务完全启动。
- 运维集控接口可能需要重试1-2次才能正常响应,属于正常现象。
- 按接口调用要求中的重试机制执行即可。
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论