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

docs(deploy): 更新部署文档强调执行操作重要性并新增ARM Ubuntu自动化部署脚本

- 在多个部署文档中强化了严格根据文档执行操作的提示
- 新增ARM Ubuntu自动化部署脚本(deploy_arm_ubuntu_976.py)
- 实现SSH连接、部署包上传、MD5校验、解压部署等功能
- 集成API接口验证、容器状态检查、安全扫描修复等验证机制
- 添加Nacos认证绕过漏洞修复和EMQX MQTT弱密码安全加固
- 生成详细的部署分析报告和日志记录功能
上级 c15c2ca2
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
X86欧拉部署 - 重建Python容器并启动服务
"""
import paramiko
import time
import sys
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
HOST = '192.168.5.52'
USER = 'root'
PASS = 'Ubains@123'
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, username=USER, password=PASS, timeout=30, look_for_keys=False, allow_agent=False)
def run(cmd, timeout=60):
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=timeout)
out = stdout.read().decode('utf-8', errors='replace')
err = stderr.read().decode('utf-8', errors='replace')
rc = stdout.channel.recv_exit_status()
return rc, out, err
start_time = time.time()
# ============ 创建ucmdb ============
print('[1] 创建ucmdb容器...')
rc, out, err = run('docker run -d '
'--name ucmdb '
'--hostname ucmdb '
'--mac-address="02:42:ac:11:00:07" '
'--entrypoint /bin/bash '
'-v /data/services/api/python-cmdb:/var/www/html '
'-v /data/middleware:/data/middleware '
'-v /etc/localtime:/etc/localtime:ro '
'--restart=always '
'139.9.60.86:5000/upython:v16 '
'-c "cd /var/www/html && ./start.sh"')
print(f' rc={rc} id={out.strip()[:12]}')
if rc != 0:
print(f' err: {err.strip()[:300]}')
# ============ 创建uvoice ============
print()
print('[2] 创建uvoice容器...')
rc, out, err = run('docker run -d '
'--name uvoice '
'--hostname uvoice '
'--mac-address="02:42:ac:11:00:08" '
'-v /data/services/api/python-voice:/var/www/html/api '
'-v /data/middleware:/data/middleware '
'-v /data/third_party:/data/third_party '
'-v /etc/localtime:/etc/localtime:ro '
'--restart=always '
'139.9.60.86:5000/upython:v13 '
'/root/start.sh')
print(f' rc={rc} id={out.strip()[:12]}')
if rc != 0:
print(f' err: {err.strip()[:300]}')
time.sleep(15)
# ============ 容器状态 ============
print()
print('[3] 所有容器状态:')
rc, out, _ = run('docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"')
print(out)
# ============ 检查Python服务 ============
print('[4] ucmdb内关键进程:')
rc, out, _ = run('docker exec ucmdb ps aux 2>&1 | grep -cE "httpd|uwsgi|python"')
print(f' 关键进程数: {out.strip()}')
print()
print('[5] uvoice内关键进程:')
rc, out, _ = run('docker exec uvoice ps aux 2>&1 | grep -cE "httpd|nginx|python|mosquitto"')
print(f' 关键进程数: {out.strip()}')
total = int(time.time() - start_time)
print(f'\n用时: {total}秒')
ssh.close()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""仅上传部署包到ARM Ubuntu服务器"""
import paramiko
import os
import sys
import time
HOST = "192.168.9.76"
LOCAL_TAR = r"Z:\发布版本\03服务器部署\15新统一平台\ARM部署包\全量版\版本更新-待验证\arm_offline_auto_unifiedPlatform.tar.gz"
LOCAL_MD5 = r"Z:\发布版本\03服务器部署\15新统一平台\ARM部署包\全量版\版本更新-待验证\arm_offline_auto_unifiedPlatform.tar.gz.md5"
REMOTE_DIR = "/home/admin/"
LOG = os.path.join(os.path.dirname(os.path.abspath(__file__)), "reports", "upload_progress.log")
pkg_size = os.path.getsize(LOCAL_TAR)
print(f"Uploading {pkg_size/1024/1024/1024:.2f} GB to {HOST}:{REMOTE_DIR}")
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, username='admin', password='Ubains@123', timeout=30)
# Clean old partial files
ssh.exec_command("rm -f /home/admin/arm_offline_auto_unifiedPlatform.tar.gz /home/admin/arm_offline_auto_unifiedPlatform.tar.gz.md5")
time.sleep(2)
sftp = ssh.open_sftp()
last = [0]
def progress(transferred, total):
if transferred - last[0] > 200 * 1024 * 1024:
pct = transferred * 100 // total
mb_t = transferred // (1024*1024)
mb_total = total // (1024*1024)
msg = f"Upload: {pct}% ({mb_t}MB/{mb_total}MB)"
print(msg, flush=True)
with open(LOG, 'a') as f:
f.write(msg + '\n')
last[0] = transferred
print("Starting SFTP upload...", flush=True)
sftp.put(LOCAL_TAR, f"{REMOTE_DIR}arm_offline_auto_unifiedPlatform.tar.gz", callback=progress)
print("tar.gz done, uploading md5...", flush=True)
sftp.put(LOCAL_MD5, f"{REMOTE_DIR}arm_offline_auto_unifiedPlatform.tar.gz.md5")
sftp.close()
# sudo move to /data/
print("Moving to /data/...", flush=True)
stdin, stdout, stderr = ssh.exec_command("echo 'Ubains@123' | sudo -S mv /home/admin/arm_offline_auto_unifiedPlatform.tar.gz /home/admin/arm_offline_auto_unifiedPlatform.tar.gz.md5 /data/")
stdout.read()
print("Upload complete!", flush=True)
ssh.close()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
上传部署包到192.168.5.69服务器
使用paramiko的SFTP功能上传大文件,带进度显示
"""
import sys
import os
import time
import stat
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
import paramiko
HOST = '192.168.5.69'
USER = 'root'
PASS = 'Ubains@123'
# 部署包路径
TAR_GZ = r'Z:\发布版本\03服务器部署\15新统一平台\X86部署包\全量版\offline_auto_unifiedPlatform.tar.gz'
MD5_FILE = r'Z:\发布版本\03服务器部署\15新统一平台\X86部署包\全量版\offline_auto_unifiedPlatform.tar.gz.md5'
def progress(transferred, total):
"""显示上传进度"""
percent = (transferred / total) * 100
mb_transferred = transferred / (1024 * 1024)
mb_total = total / (1024 * 1024)
bar_len = 50
filled = int(bar_len * transferred / total)
bar = '=' * filled + '-' * (bar_len - filled)
sys.stdout.write(f'\r [{bar}] {percent:.1f}% ({mb_transferred:.0f}/{mb_total:.0f} MB)')
sys.stdout.flush()
def main():
print(f"连接SSH服务器 {HOST}...")
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, username=USER, password=PASS, timeout=30, look_for_keys=False, allow_agent=False)
print("SSH连接成功")
sftp = ssh.open_sftp()
# 1. 上传MD5文件
print(f"\n上传MD5文件: {os.path.basename(MD5_FILE)}")
local_md5 = MD5_FILE
if os.path.exists(local_md5):
sftp.put(local_md5, '/data/offline_auto_unifiedPlatform.tar.gz.md5')
print(" MD5文件上传完成")
else:
print(f" [WARN] MD5文件不存在: {local_md5}")
# 2. 检查服务器上是否已有部署包
print(f"\n检查服务器上是否已有部署包...")
try:
remote_stat = sftp.stat('/data/offline_auto_unifiedPlatform.tar.gz')
remote_size = remote_stat.st_size
local_size = os.path.getsize(TAR_GZ)
print(f" 服务器已有文件: {remote_size / (1024**3):.2f} GB")
print(f" 本地文件大小: {local_size / (1024**3):.2f} GB")
if abs(remote_size - local_size) < 1024: # 允许1KB误差
print(f" [OK] 服务器上已有完整的部署包,跳过上传")
sftp.close()
ssh.close()
return 0
else:
print(f" 文件大小不一致,需要重新上传")
except IOError:
print(f" 服务器上无部署包,开始上传")
# 3. 上传tar.gz
local_size = os.path.getsize(TAR_GZ)
print(f"\n上传部署包: {os.path.basename(TAR_GZ)}")
print(f"文件大小: {local_size / (1024**3):.2f} GB")
print(f"预计需要较长时间,请耐心等待...\n")
start_time = time.time()
sftp.put(TAR_GZ, '/data/offline_auto_unifiedPlatform.tar.gz', callback=progress)
elapsed = time.time() - start_time
print(f"\n\n上传完成! 用时: {elapsed:.0f}秒 ({elapsed/60:.1f}分钟)")
speed = local_size / elapsed / (1024 * 1024) # MB/s
print(f"平均速度: {speed:.1f} MB/s")
# 4. 验证上传文件大小
print(f"\n验证文件完整性...")
remote_stat = sftp.stat('/data/offline_auto_unifiedPlatform.tar.gz')
print(f" 服务器文件大小: {remote_stat.st_size}")
print(f" 本地文件大小: {local_size}")
if remote_stat.st_size == local_size:
print(f" [OK] 文件大小一致,上传成功")
else:
print(f" [WARN] 文件大小不一致!", file=sys.stderr)
# 5. 执行MD5校验
print(f"\n执行MD5校验...")
stdin, stdout, stderr = ssh.exec_command('cd /data && md5sum -c offline_auto_unifiedPlatform.tar.gz.md5', timeout=300)
out = stdout.read().decode('utf-8', errors='replace')
print(f" 校验结果: {out.strip()}")
sftp.close()
ssh.close()
print("\n部署包上传完成!")
return 0
if __name__ == '__main__':
sys.exit(main())
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""X86欧拉 - 服务验证(容器+API+日志)"""
import paramiko
import time
import sys
import requests
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
HOST = '192.168.5.52'
USER = 'root'
PASS = 'Ubains@123'
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, username=USER, password=PASS, timeout=10, look_for_keys=False, allow_agent=False)
stdin, stdout, stderr = ssh.exec_command('docker ps --format "table {{.Names}}\t{{.Status}}"', timeout=30)
out = stdout.read().decode('utf-8', errors='replace')
err = stderr.read().decode('utf-8', errors='replace')
def run2(cmd):
sin, sout, serr = ssh.exec_command(cmd, timeout=30)
o = sout.read().decode('utf-8', errors='replace')
return o
# ============ 1. 容器状态 ============
print('=' * 50)
print('1. Docker容器状态')
print('=' * 50)
print(run2('docker ps --format "table {{.Names}}\t{{.Status}}"'))
# ============ 2. 对外接口测试(5次重试,间隔30秒) ============
print('=' * 50)
print('2. 对外接口测试(5次重试)')
print('=' * 50)
url = f'https://{HOST}/exapi/message/getMsgPageList'
extapi_ok = False
for i in range(1, 6):
try:
resp = requests.get(url, verify=False, timeout=30)
text = resp.text[:200]
if '无效token' in resp.text or 'Full authentication' in resp.text:
print(f' 第{i}次: 成功 - {text[:100]}')
extapi_ok = True
break
else:
print(f' 第{i}次: 未就绪 - {text[:100]}')
except Exception as e:
print(f' 第{i}次: 异常 - {str(e)[:100]}')
if i < 5:
print(' 等待30秒...')
time.sleep(30)
# ============ 3. Java进程检查 ============
print()
print('=' * 50)
print('3. Java进程检查')
print('=' * 50)
print(f' ujava2内Java进程: {run2("docker exec ujava2 ps aux | grep [j]ava | wc -l").strip()}个')
print(f' 宿主机extapi: {run2("ps aux | grep meeting-api | grep -v grep | wc -l").strip()}个')
# ============ 4. 服务日志 ============
print()
print('=' * 50)
print('4. 服务日志检查')
print('=' * 50)
logs = {
'预定对外': '/data/services/api/java-meeting/java-meeting-extapi/logs/ubains-INFO-AND-ERROR.log',
'预定对内': '/data/services/api/java-meeting/java-meeting2.0/logs/ubains-INFO-AND-ERROR.log',
'运维服务': '/data/services/api/python-cmdb/log/uinfo.log',
'讯飞服务': '/data/services/api/python-voice/log/uinfo.log',
}
for name, path in logs.items():
tail = run2(f'tail -3 {path} 2>/dev/null')
if tail.strip():
last_line = tail.strip().split('\n')[-1][:120]
print(f' {name}: {last_line}')
else:
print(f' {name}: 日志文件不存在或为空')
ssh.close()
print()
print(f'对外接口状态: {"已就绪" if extapi_ok else "未就绪(需等待服务完全启动)"}')
......@@ -43,7 +43,7 @@
1. 目标服务器登录
- 登录目标服务器,并切换到root用户。
2. 部署执行
- 严格根据部署文档执行部署操作!!!
- 严格根据部署文档执行部署操作!!!严格根据部署文档执行部署操作!!!严格根据部署文档执行部署操作!!!
- 解压缩过程中禁止中断操作!!!
- 部署文档中提及是执行`new_auto.sh`,但你需要执行`new_auto.sh --all`,可以跳过系统选择菜单的选择操作,默认部署所有系统,但是例如服务器空间检查、系统类型检查以及服务器IP检查还是需要交互确认。
- 不要自己乱操作,严格按照文档操作执行即可。
......
......@@ -43,7 +43,7 @@
1. 目标服务器登录
- 登录目标服务器,并切换到root用户。
2. 部署执行
- 严格根据部署文档执行部署操作!!!
- 严格根据部署文档执行部署操作!!!严格根据部署文档执行部署操作!!!严格根据部署文档执行部署操作!!!
- 解压缩过程中禁止中断操作!!!
- 部署文档中提及是执行`new_auto.sh`,但你需要执行`new_auto.sh --all`,可以跳过系统选择菜单的选择操作,默认部署所有系统,但是例如服务器空间检查、系统类型检查以及服务器IP检查还是需要交互确认。
- 不要自己乱操作,严格按照文档操作执行即可。
......
......@@ -43,7 +43,7 @@
1. 目标服务器登录
- 登录目标服务器,并切换到root用户。
2. 部署执行
- 严格根据部署文档执行部署操作!!!
- 严格根据部署文档执行部署操作!!!严格根据部署文档执行部署操作!!!严格根据部署文档执行部署操作!!!
- 解压缩过程中禁止中断操作!!!
- 部署文档中提及是执行`new_auto.sh`,但你需要执行`new_auto.sh --all`,可以跳过系统选择菜单的选择操作,默认部署所有系统,但是例如服务器空间检查、系统类型检查以及服务器IP检查还是需要交互确认。
- 不要自己乱操作,严格按照文档操作执行即可。
......
......@@ -43,7 +43,7 @@
1. 目标服务器登录
- 登录目标服务器,并切换到root用户。
2. 部署执行
- 严格根据部署文档执行部署操作!!!
- 严格根据部署文档执行部署操作!!!严格根据部署文档执行部署操作!!!严格根据部署文档执行部署操作!!!
- 解压缩过程中禁止中断操作!!!
- 部署文档中提及是执行`new_auto.sh`,但你需要执行`new_auto.sh --all`,可以跳过系统选择菜单的选择操作,默认部署所有系统,但是例如服务器空间检查、系统类型检查以及服务器IP检查还是需要交互确认。
- 不要自己乱操作,严格按照文档操作执行即可。
......
......@@ -43,7 +43,7 @@
1. 目标服务器登录
- 登录目标服务器,并切换到root用户。
2. 部署执行
- 严格根据部署文档执行部署操作!!!
- 严格根据部署文档执行部署操作!!!严格根据部署文档执行部署操作!!!严格根据部署文档执行部署操作!!!
- 解压缩过程中禁止中断操作!!!
- 部署文档中提及是执行`new_auto.sh`,但你需要执行`new_auto.sh --all`,可以跳过系统选择菜单的选择操作,默认部署所有系统,但是例如服务器空间检查、系统类型检查以及服务器IP检查还是需要交互确认。
- 不要自己乱操作,严格按照文档操作执行即可。
......
......@@ -43,7 +43,7 @@
1. 目标服务器登录
- 登录目标服务器,并切换到root用户。
2. 部署执行
- 严格根据部署文档执行部署操作!!!
- 严格根据部署文档执行部署操作!!!严格根据部署文档执行部署操作!!!严格根据部署文档执行部署操作!!!
- 解压缩过程中禁止中断操作!!!
- 部署文档中提及是执行`new_auto.sh`,但你需要执行`new_auto.sh --all`,可以跳过系统选择菜单的选择操作,默认部署所有系统,但是例如服务器空间检查、系统类型检查以及服务器IP检查还是需要交互确认。
- 不要自己乱操作,严格按照文档操作执行即可。
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论