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

docs(deployment): 更新远程自动化部署需求文档并移除相关脚本

- 更新验收要求中的服务启动检查条件,从检查版本信息改为检查"结束数据库调整"日志
- 移除远程自动化部署相关的bash脚本文件
- 移除Python自动化部署脚本和交互式处理脚本
- 移除完整的Python部署自动化类实现代码
- 保留部署需求文档的核心内容和流程说明
上级 29f56822
@echo off
REM Accept SSH host key for remote server
REM Usage: accept_host_key.bat
setlocal enabledelayedexpansion
set SERVER_IP=192.168.5.52
set SSH_PORT=22
set USERNAME=root
set PASSWORD=Ubains@123
echo ========================================
echo Accepting SSH host key for %SERVER_IP%
echo ========================================
REM Use plink to accept host key (will prompt)
echo Please accept the host key when prompted...
echo.
plink.exe -pw %PASSWORD% -P %SSH_PORT% %USERNAME%@%SERVER_IP% echo "Host key accepted"
echo.
echo ========================================
echo Host key acceptance completed
echo ========================================
endlocal
# Complete Acceptance Test Script
$PlinkPath = "E:\GithubData\ubains-module-test\AuxiliaryTool\ScriptTool\RemoteDeploy\plink.exe"
function Invoke-SSH {
param([string]$Command)
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw Ubains@123 -P 22 root@192.168.5.52 $Command"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit(120000)
return $p.StandardOutput.ReadToEnd()
}
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Complete Acceptance Test" -ForegroundColor Cyan
Write-Host "Server: 192.168.5.52" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# Test 1: Container Status
Write-Host "Test 1: Container Status Check" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Gray
$containers = Invoke-SSH -Command "docker ps --format 'table {{.Names}}\t{{.Status}}'"
Write-Host $containers
Write-Host ""
# Test 2: External Service Log Check
Write-Host "Test 2: External Service Log (SYSTEMVERSION Check)" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Gray
$extApiLog = Invoke-SSH -Command "tail -100 /data/services/api/java-meeting/java-meeting-extapi/logs/ubains-INFO-AND-ERROR.log"
if ($extApiLog -match "SYSTEMVERSION :: target_api_integration") {
Write-Host "✅ External service log: SYSTEMVERSION found - PASS" -ForegroundColor Green
} else {
Write-Host "⚠️ External service log: SYSTEMVERSION not found - checking again in 10 min..." -ForegroundColor Yellow
Start-Sleep -Seconds 600
$extApiLogRetry = Invoke-SSH -Command "tail -100 /data/services/api/java-meeting/java-meeting-extapi/logs/ubains-INFO-AND-ERROR.log"
if ($extApiLogRetry -match "SYSTEMVERSION") {
Write-Host "✅ External service log: SYSTEMVERSION found (after retry) - PASS" -ForegroundColor Green
} else {
Write-Host "❌ External service log: SYSTEMVERSION not found - FAIL" -ForegroundColor Red
Write-Host "Last log lines:" -ForegroundColor Gray
Write-Host $extApiLogRetry
}
}
Write-Host ""
# Test 3: API Endpoint Tests
Write-Host "Test 3: Service API Endpoint Tests" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Gray
$apiTests = @{
"ExtAPI" = @{URL = "https://192.168.5.52/exapi/message/getMsgPageList"; Expected = "A0076"}
"Meeting" = @{URL = "https://192.168.5.52/meetingV3/api/systemConfiguration/globalConfig?companyNumber=CN-SZ-00-0201"; Expected = "A0078"}
"Monitor" = @{URL = "https://192.168.5.52/monitor/api2/api/servermonitor/"; Expected = "40000014"}
"Voice" = @{URL = "https://192.168.5.52/voice/api/iflytek/roommaster?company_id=1&user_id=8&company_secret=57d00f9f-020f-5f1f-b788-55fae843bceb&getall=1"; Expected = "40000003"}
}
foreach ($api in $apiTests.Keys) {
$test = $apiTests[$api]
Write-Host "Testing $api..." -ForegroundColor Cyan
$result = Invoke-SSH -Command "curl -k '$($test.URL)' 2>/dev/null"
if ($result -match $test.Expected) {
Write-Host "✅ $api: PASS" -ForegroundColor Green
} elseif ($result -match "nginx|Error") {
Write-Host "❌ $api: FAIL (nginx error page)" -ForegroundColor Red
} else {
Write-Host "⚠️ $api: UNKNOWN RESPONSE" -ForegroundColor Yellow
}
}
Write-Host ""
# Test 4: Service Status Summary
Write-Host "Test 4: Service Status Summary" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Gray
$javaProcesses = Invoke-SSH -Command "ps aux | grep java | grep -v grep | wc -l"
$pythonProcesses = Invoke-SSH -Command "ps aux | grep 'python.*uwsgi\|python.*httpd' | grep -v grep | wc -l"
Write-Host "Java processes: $($javaProcesses.Trim())" -ForegroundColor Cyan
Write-Host "Python service processes: $($pythonProcesses.Trim())" -ForegroundColor Cyan
# Check specific services
$services = @(
@{Name = "ExtAPI"; Path = "/data/services/api/java-meeting/java-meeting-extapi"},
@{Name = "InnerAPI"; Path = "/data/services/api/java-meeting/java-meeting2.0"},
@{Name = "Monitor"; Path = "/data/services/api/python-cmdb"},
@{Name = "Voice"; Path = "/data/services/api/python-voice"}
)
foreach ($svc in $services) {
$exists = Invoke-SSH -Command "test -d '$($svc.Path)' && echo 'exists' || echo 'not_found'"
if ($exists -match "exists") {
Write-Host "✅ $($svc.Name): Directory exists" -ForegroundColor Green
} else {
Write-Host "❌ $($svc.Name): Directory not found" -ForegroundColor Red
}
}
Write-Host ""
# Final Summary
Write-Host "========================================" -ForegroundColor Green
Write-Host "Acceptance Test Summary" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host ""
Write-Host "Next Steps:" -ForegroundColor Yellow
Write-Host "1. System Authorization: https://192.168.5.52/#/LoginConfig" -ForegroundColor Gray
Write-Host " Verification code: csba" -ForegroundColor Gray
Write-Host " License file: E:\自动化部署\X86-5.52\license.zip" -ForegroundColor Gray
Write-Host ""
Write-Host "2. Create Company Admin: https://192.168.5.52/#/LoginAdmin" -ForegroundColor Gray
Write-Host ""
Write-Host "========================================" -ForegroundColor Green
#!/usr/bin/env expect
# -*- coding: utf-8 -*-
#
# 自动化部署expect脚本
# 用于自动响应部署脚本的交互式提示
# 设置超时时间
set timeout 300
# 服务器信息
set host "192.168.5.52"
set user "root"
set password "Ubains@123"
set deploy_dir "/data/offline_auto_unifiedPlatform"
# 启动SSH连接
spawn ssh $user@$host
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "$password\r" }
}
# 等待shell准备就绪
expect "#"
send "cd $deploy_dir\r"
# 执行部署脚本
send "./new_auto.sh --all\r"
# 交互式响应
expect {
# 服务器规格不符合提示
"是否继续执行脚本" {
send "y\r"
exp_continue
}
# 确认网口
"确认网口信息是否正确" {
send "\r"
exp_continue
}
# 确认时间
"服务器日期和时间" {
send "\r"
exp_continue
}
"时间不正确" {
send "y\r"
exp_continue
}
# 确认IP
"服务器ip是否正确" {
send "\r"
exp_continue
}
"请输入正确的IP" {
send "192.168.5.52\r"
exp_continue
}
"否" {
send "\r"
exp_continue
}
# 系统部署选择(--all应该跳过)
"确认需部署的系统" {
send "\r"
exp_continue
}
# 部署完成提示
"自动化部署完成" {
send "source /etc/profile\r"
}
# EOF - 脚本结束
eof {
puts "\n部署脚本执行完成"
}
timeout {
puts "\n等待超时,部署可能仍在进行中..."
send "\r"
exp_continue
}
}
# 等待shell返回
expect "#"
send "echo \"Deploy completed\"\r"
expect "#"
send "exit\r"
# 等待expect结束
expect eof
#!/usr/bin/env pwsh
# ============================================================================
# 远程自动化部署脚本 - 新统一平台
# 功能:自动完成新统一平台的完整部署流程
# 作者:自动化运维团队
# 创建时间:2026-05-14
# ============================================================================
#Requires -Version 5.1
<#
.SYNOPSIS
新统一平台远程自动化部署脚本
.DESCRIPTION
本脚本用于自动完成新统一平台的部署,包括:
1. 部署包准备与上传
2. 自动化部署脚本执行
3. 服务状态检查
4. 接口验证测试
5. 部署报告生成
.PARAMETER ServerIP
目标服务器IP地址
.PARAMETER Architecture
服务器架构类型 (X86/ARM)
.EXAMPLE
.\auto_deploy.ps1 -ServerIP "192.168.5.52" -Architecture "X86"
#>
# ============================================================================
# 参数定义
# ============================================================================
param(
[Parameter(Mandatory=$false)]
[string]$ServerIP = "192.168.5.52",
[Parameter(Mandatory=$false)]
[ValidateSet("X86", "ARM")]
[string]$Architecture = "X86",
[Parameter(Mandatory=$false)]
[string]$Username = "root",
[Parameter(Mandatory=$false)]
[string]$Password = "Ubains@123",
[Parameter(Mandatory=$false)]
[int]$SSHPort = 22
)
# ============================================================================
# 脚本初始化
# ============================================================================
# 设置错误处理
$ErrorActionPreference = "Continue"
# 设置控制台输出编码为UTF-8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
# 获取脚本根目录
$ScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
# 定义目录路径
$PackagesDir = Join-Path $ScriptRoot "packages"
$ReportsDir = Join-Path $ScriptRoot "reports"
$TempDir = Join-Path $ScriptRoot "temp"
# 创建必要的目录结构
$Directories = @($PackagesDir, $ReportsDir, $TempDir)
foreach ($Dir in $Directories) {
if (-not (Test-Path $Dir)) {
New-Item -ItemType Directory -Path $Dir -Force | Out-Null
}
}
# 定义全局变量
$Global:SSHTimeout = 300 # SSH连接超时时间(秒)- 部署需要更长时间
$Global:MaxRetry = 3 # 最大重试次数
$Global:PlinkPath = Join-Path $ScriptRoot "plink.exe"
$Global:PscpPath = Join-Path $ScriptRoot "pscp.exe"
# 定义部署配置
$DeployConfig = @{
X86 = @{
NetworkShare = '\\192.168.9.9\发布版本\03服务器部署\临时使用-新统一平台\X86部署包\全量版'
LicenseFile = '\\192.168.9.9\发布版本\03服务器部署\临时使用-新统一平台\测试授权文件-请勿使用\5.52授权文件\license.zip'
DeployDoc = '\\192.168.9.9\发布版本\03服务器部署\临时使用-新统一平台\X86部署包\新统一平台自动化部署操作指导.docx'
}
ARM = @{
NetworkShare = '\\192.168.9.9\发布版本\03服务器部署\临时使用-新统一平台\ARM部署包-请勿使用'
LicenseFile = '\\192.168.9.9\发布版本\03服务器部署\临时使用-新统一平台\测试授权文件-请勿使用\9.76授权文件\license.zip'
DeployDoc = '\\192.168.9.9\发布版本\03服务器部署\临时使用-新统一平台\ARM部署包-请勿使用\新统一平台自动化部署操作指导.docx'
}
}
# 定义日志路径配置
$LogPaths = @{
ExtAPI = "/data/services/api/java-meeting/java-meeting-extapi/logs/ubains-INFO-AND-ERROR.log"
InnerAPI = "/data/services/api/java-meeting/java-meeting2.0/logs/ubains-INFO-AND-ERROR.log"
Monitor = "/data/services/api/python-cmdb/log/uinfo.log"
Voice = "/data/services/api/python-voice/log/uinfo.log"
}
# 定义接口测试配置
$APITests = @{
ExtAPI = @{
URL = 'https://{0}/exapi/message/getMsgPageList'
Expected = '{"success":false,"code":"A0076","message":"无效token"'
}
Meeting = @{
URL = 'https://{0}/meetingV3/api/systemConfiguration/globalConfig?companyNumber=CN-SZ-00-0201'
Expected = '{"success":false,"code":"A0078","message":"请求错误,accessToken为空"'
}
Monitor = @{
URL = 'https://{0}/monitor/api2/api/servermonitor/'
Expected = '{"success":0,"data":[{"code":40000014,"error":"用户不存在或重新登录或已退出"'
}
Voice = @{
URL = 'https://{0}/voice/api/iflytek/roommaster?company_id=1&user_id=8&company_secret=57d00f9f-020f-5f1f-b788-55fae843bceb&getall=1'
Expected = '{"success":false,"data":[{"code":40000003,"error":"缺少关键参数"'
}
}
# 全局执行记录
$Global:ExecutionLog = @()
$Global:DeployResults = @{}
# ============================================================================
# 日志函数
# ============================================================================
function Write-LogInfo {
param([string]$Message)
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogMessage = "[$Timestamp] [INFO] $Message"
Write-Host $LogMessage
$Global:ExecutionLog += $LogMessage
}
function Write-LogWarn {
param([string]$Message)
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogMessage = "[$Timestamp] [WARN] $Message"
Write-Host $LogMessage -ForegroundColor Yellow
$Global:ExecutionLog += $LogMessage
}
function Write-LogError {
param([string]$Message)
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogMessage = "[$Timestamp] [ERROR] $Message"
Write-Host $LogMessage -ForegroundColor Red
$Global:ExecutionLog += $LogMessage
}
function Write-LogOk {
param([string]$Message)
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogMessage = "[$Timestamp] [OK] $Message"
Write-Host $LogMessage -ForegroundColor Green
$Global:ExecutionLog += $LogMessage
}
function Write-LogStep {
param([string]$Message)
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogMessage = "[$Timestamp] [STEP] $Message"
Write-Host $LogMessage -ForegroundColor Cyan
$Global:ExecutionLog += $LogMessage
}
# ============================================================================
# SSH连接函数
# ============================================================================
function Invoke-SSHCommand {
param(
[string]$Command,
[int]$Timeout = $Global:SSHTimeout
)
$PlinkArgs = @(
"-pw", $Password
"-P", $SSHPort
"-timeout", $Timeout
"$($Username)@$($ServerIP)"
$Command
)
try {
$Result = & $Global:PlinkPath $PlinkArgs 2>&1
return @{
Success = $?
Output = $Result -join "`n"
ExitCode = if ($?) { 0 } else { 1 }
}
}
catch {
return @{
Success = $false
Output = $_.Exception.Message
ExitCode = 1
}
}
}
function Test-SSHConnection {
Write-LogStep "步骤1: 测试SSH连接"
Write-LogInfo "正在连接服务器 ${ServerIP}:${SSHPort}..."
for ($i = 1; $i -le $Global:MaxRetry; $i++) {
$Result = Invoke-SSHCommand -Command "echo 'connection_ok'"
if ($Result.Output -match "connection_ok") {
Write-LogOk "连接成功"
$Global:DeployResults.Connection = "成功"
return $true
}
else {
Write-LogWarn "连接失败,正在重试 ($i/$Global:MaxRetry)..."
Start-Sleep -Seconds 2
}
}
Write-LogError "连接失败,已达到最大重试次数"
$Global:DeployResults.Connection = "失败"
return $false
}
# ============================================================================
# 部署包处理函数
# ============================================================================
function Copy-FromNetworkShare {
param(
[string]$NetworkPath,
[string]$Destination
)
Write-LogInfo "正在从网络共享复制: $NetworkPath"
try {
if (Test-Path $NetworkPath) {
Copy-Item -Path $NetworkPath -Destination $Destination -Recurse -Force
Write-LogOk "复制成功"
return $true
}
else {
Write-LogError "网络共享路径不存在: $NetworkPath"
return $false
}
}
catch {
Write-LogError "复制失败: $_"
return $false
}
}
function Upload-DeployPackage {
Write-LogStep "步骤2: 准备并上传部署包"
$Config = $DeployConfig[$Architecture]
$LocalPackageDir = Join-Path $TempDir "deploy_package"
# 清理并创建本地临时目录
if (Test-Path $LocalPackageDir) {
Remove-Item -Path $LocalPackageDir -Recurse -Force
}
New-Item -ItemType Directory -Path $LocalPackageDir -Force | Out-Null
# 从网络共享复制部署包
Write-LogInfo "正在从网络共享复制部署包..."
$CopyResult = Copy-FromNetworkShare -NetworkPath $Config.NetworkShare -Destination $LocalPackageDir
if (-not $CopyResult) {
Write-LogError "部署包复制失败"
$Global:DeployResults.PackageUpload = "失败: 网络共享复制失败"
return $false
}
# 获取部署包文件列表
$PackageFiles = Get-ChildItem -Path $LocalPackageDir -Recurse -File
Write-LogInfo "找到 $($PackageFiles.Count) 个文件"
# 在服务器上创建部署目录
$ServerDeployDir = "/home/deploy"
Write-LogInfo "正在创建服务器部署目录: $ServerDeployDir"
$MkdirResult = Invoke-SSHCommand -Command "mkdir -p $ServerDeployDir && echo 'created'"
if ($MkdirResult.Output -notmatch "created") {
Write-LogError "创建服务器部署目录失败"
$Global:DeployResults.PackageUpload = "失败: 无法创建服务器目录"
return $false
}
# 上传部署包文件
Write-LogInfo "正在上传部署包到服务器..."
$UploadedCount = 0
$FailedFiles = @()
foreach ($File in $PackageFiles) {
$RelativePath = $File.FullName.Substring($LocalPackageDir.Length + 1)
$RemotePath = "$ServerDeployDir/$RelativePath"
$RemoteDir = Split-Path $RemotePath -Parent
# 创建远程目录结构
$CreateDirResult = Invoke-SSHCommand -Command "mkdir -p '$RemoteDir'"
# 上传文件
try {
$PscpArgs = @(
"-pw", $Password
"-P", $SSHPort
"-batch"
$File.FullName
"${Username}@${ServerIP}:$RemotePath"
)
$UploadResult = & $Global:PscpPath $PscpArgs 2>&1
if ($LASTEXITCODE -eq 0) {
$UploadedCount++
if ($UploadedCount % 10 -eq 0) {
Write-LogInfo "已上传 $UploadedCount 个文件..."
}
}
else {
$FailedFiles += $RelativePath
}
}
catch {
$FailedFiles += $RelativePath
}
}
Write-LogInfo "上传完成: 成功 $UploadedCount 个,失败 $($FailedFiles.Count) 个"
if ($FailedFiles.Count -gt 0) {
Write-LogWarn "部分文件上传失败:"
foreach ($FailedFile in $FailedFiles) {
Write-LogWarn " - $FailedFile"
}
}
$Global:DeployResults.PackageUpload = "成功: $UploadedCount 个文件"
Write-LogOk "部署包上传完成"
return $true
}
# ============================================================================
# 部署执行函数
# ============================================================================
function Invoke-DeployScript {
Write-LogStep "步骤3: 执行自动化部署脚本"
$ServerDeployDir = "/home/deploy"
# 查找部署脚本
Write-LogInfo "正在查找部署脚本..."
$FindResult = Invoke-SSHCommand -Command "find $ServerDeployDir -name '*.sh' -type f 2>/dev/null | head -20"
$DeployScripts = $FindResult.Output -split "`n" | Where-Object { $_ -match '\S' }
if ($DeployScripts.Count -eq 0) {
Write-LogError "未找到部署脚本"
Write-LogInfo "服务器上的文件列表:"
$ListResult = Invoke-SSHCommand -Command "ls -la $ServerDeployDir"
Write-Host $ListResult.Output
$Global:DeployResults.DeployExecution = "失败: 未找到部署脚本"
return $false
}
Write-LogInfo "找到以下部署脚本:"
foreach ($Script in $DeployScripts) {
Write-Host " - $Script"
}
# 查找主部署脚本(通常包含 deploy、auto、install 等关键词)
$MainScript = $DeployScripts | Where-Object {
$_ -match '(auto_deploy|deploy|install|setup)' -and $_ -notmatch '\.(bak|backup|old)'
} | Select-Object -First 1
if (-not $MainScript) {
$MainScript = $DeployScripts[0]
}
Write-LogInfo "选择主部署脚本: $MainScript"
# 赋予执行权限
Write-LogInfo "正在设置脚本执行权限..."
$ChmodResult = Invoke-SSHCommand -Command "chmod +x '$MainScript' && echo 'chmod_ok'"
if ($ChmodResult.Output -notmatch "chmod_ok") {
Write-LogWarn "设置执行权限失败,尝试继续执行"
}
# 执行部署脚本
Write-LogWarn "开始执行部署脚本,预计耗时约40分钟..."
Write-LogInfo "部署输出将实时显示..."
# 使用 nohup 在后台执行部署,并记录日志
$LogFile = "/tmp/deploy_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
$DeployCommand = "cd '$ServerDeployDir' && bash '$MainScript' 2>&1 | tee $LogFile"
Write-LogInfo "执行命令: $DeployCommand"
# 执行部署(使用长超时时间)
$DeployResult = Invoke-SSHCommand -Command $DeployCommand -Timeout 3600
Write-LogInfo "部署脚本执行完成"
Write-Host "`n========== 部署输出 ==========" -ForegroundColor Cyan
Write-Host $DeployResult.Output
Write-Host "========== 部署输出结束 ==========`n" -ForegroundColor Cyan
# 检查部署结果
if ($DeployResult.ExitCode -eq 0) {
Write-LogOk "部署脚本执行成功"
$Global:DeployResults.DeployExecution = "成功"
$Global:DeployResults.DeployLog = $LogFile
return $true
}
else {
Write-LogError "部署脚本执行失败,退出码: $($DeployResult.ExitCode)"
$Global:DeployResults.DeployExecution = "失败: 退出码 $($DeployResult.ExitCode)"
$Global:DeployResults.DeployLog = $LogFile
return $false
}
}
# ============================================================================
# 服务检查函数
# ============================================================================
function Test-ContainerStatus {
Write-LogStep "步骤4: 检查容器状态"
# 检查Docker是否运行
$DockerCheck = Invoke-SSHCommand -Command "docker ps --format 'table {{.Names}}\t{{.Status}}' 2>/dev/null"
if ($DockerCheck.ExitCode -ne 0) {
Write-LogError "Docker未运行或无法访问"
$Global:DeployResults.ContainerStatus = "失败: Docker不可用"
return $false
}
Write-Host "`n========== 容器状态 ==========" -ForegroundColor Cyan
Write-Host $DockerCheck.Output
Write-Host "========== 容器状态结束 ==========`n" -ForegroundColor Cyan
# 检查关键容器
$RequiredContainers = @(
"ujava",
"upython",
"uredis",
"umysql",
"uemqx"
)
$ContainerStatus = @{}
foreach ($Container in $RequiredContainers) {
$CheckResult = Invoke-SSHCommand -Command "docker inspect -f '{{.State.Running}}' $Container 2>/dev/null || echo 'not_found'"
if ($CheckResult.Output -match "true") {
$ContainerStatus[$Container] = "运行中"
Write-LogOk "$Container: 运行中"
}
elseif ($CheckResult.Output -match "false") {
$ContainerStatus[$Container] = "已停止"
Write-LogWarn "$Container: 已停止"
}
else {
$ContainerStatus[$Container] = "不存在"
Write-LogError "$Container: 不存在"
}
}
$Global:DeployResults.ContainerStatus = $ContainerStatus
# 检查是否有异常容器
$FailedContainers = $ContainerStatus.GetEnumerator() | Where-Object { $_.Value -ne "运行中" }
if ($FailedContainers.Count -eq 0) {
Write-LogOk "所有关键容器状态正常"
return $true
}
else {
Write-LogWarn "部分容器状态异常"
return $false
}
}
function Test-ServiceLogs {
Write-LogStep "步骤5: 检查服务日志"
$LogChecks = @{}
# 检查对外服务日志(必须包含版本信息)
Write-LogInfo "检查对外服务日志..."
$ExtAPILog = Invoke-SSHCommand -Command "tail -100 $($LogPaths.ExtAPI) 2>/dev/null || echo 'log_not_found'"
if ($ExtAPILog.Output -match "SYSTEMVERSION :: target_api_integration") {
Write-LogOk "对外服务日志正常(已检测到版本信息)"
$LogChecks.ExtAPI = "正常"
}
elseif ($ExtAPILog.Output -match "log_not_found") {
Write-LogWarn "对外服务日志文件不存在"
$LogChecks.ExtAPI = "日志文件不存在"
}
else {
Write-LogWarn "对外服务日志未检测到版本信息,等待10分钟后重试..."
# 等待10分钟
for ($i = 1; $i -le 10; $i++) {
Write-Host "等待中... ($i/10 分钟)" -ForegroundColor Yellow
Start-Sleep -Seconds 60
}
# 重新检查
$ExtAPILogRetry = Invoke-SSHCommand -Command "tail -100 $($LogPaths.ExtAPI) 2>/dev/null"
if ($ExtAPILogRetry.Output -match "SYSTEMVERSION") {
Write-LogOk "对外服务日志正常(重试后检测到版本信息)"
$LogChecks.ExtAPI = "正常(重试后)"
}
else {
Write-LogError "对外服务日志异常(10分钟后仍未检测到版本信息)"
Write-Host "`n最后100行日志:" -ForegroundColor Yellow
Write-Host $ExtAPILogRetry.Output
$LogChecks.ExtAPI = "异常:无版本信息"
}
}
# 检查其他服务日志是否存在异常
$OtherLogs = @(
@{Name = "对内服务"; Path = $LogPaths.InnerAPI},
@{Name = "运维服务"; Path = $LogPaths.Monitor},
@{Name = "讯飞服务"; Path = $LogPaths.Voice}
)
foreach ($LogInfo in $OtherLogs) {
Write-LogInfo "检查$($LogInfo.Name)日志..."
$LogResult = Invoke-SSHCommand -Command "tail -50 $($LogInfo.Path) 2>/dev/null || echo 'not_found'"
if ($LogResult.Output -match "ERROR|Exception|Failed|failed") {
Write-LogWarn "$($LogInfo.Name)日志中发现异常信息"
$LogChecks[$LogInfo.Name] = "发现异常"
}
elseif ($LogResult.Output -match "not_found") {
Write-LogWarn "$($LogInfo.Name)日志文件不存在"
$LogChecks[$LogInfo.Name] = "日志文件不存在"
}
else {
Write-LogOk "$($LogInfo.Name)日志正常"
$LogChecks[$LogInfo.Name] = "正常"
}
}
$Global:DeployResults.ServiceLogs = $LogChecks
return $true
}
function Test-APIEndpoints {
Write-LogStep "步骤6: 测试服务接口"
$APIResults = @{}
foreach ($APIName in $APITests.Keys) {
$API = $APITests[$APIName]
$URL = $API.URL -f $ServerIP
$Expected = $API.Expected
Write-LogInfo "测试 $APIName 接口..."
# 使用curl测试接口(忽略SSL证书)
$CurlCommand = "curl -k '$URL' 2>/dev/null"
$APIResult = Invoke-SSHCommand -Command $CurlCommand -Timeout 60
# 检查是否返回预期的错误响应(表示服务正常,只是缺少认证)
if ($APIResult.Output -match $Expected.Substring(0, 20)) {
Write-LogOk "$APIName 接口正常(返回预期认证错误)"
$APIResults[$APIName] = "正常"
continue
}
# 检查是否返回nginx错误页面(表示服务未启动)
if ($APIResult.Output -match "An error occurred|nginx") {
Write-LogError "$APIName 接口异常(返回nginx错误页面)"
# 执行重试机制
$RetrySuccess = $false
for ($retry = 1; $retry -le 5; $retry++) {
Write-LogWarn "重试第 $retry 次..."
Start-Sleep -Seconds 30
$RetryResult = Invoke-SSHCommand -Command $CurlCommand -Timeout 60
if ($RetryResult.Output -match $Expected.Substring(0, 20)) {
Write-LogOk "$APIName 接口正常(重试第 $retry 次后成功)"
$APIResults[$APIName] = "正常(重试 $retry 次)"
$RetrySuccess = $true
break
}
}
if (-not $RetrySuccess) {
$APIResults[$APIName] = "异常:5次重试后仍失败"
}
}
else {
# 返回了其他响应,可能是服务问题
Write-LogWarn "$APIName 接口返回未知响应"
Write-Host "响应内容: $($APIResult.Output.Substring(0, 200))"
$APIResults[$APIName] = "未知响应"
}
}
$Global:DeployResults.APITests = $APIResults
# 检查API测试结果
$FailedAPIs = $APIResults.GetEnumerator() | Where-Object { $_.Value -like "*异常*" -or $_.Value -eq "未知响应" }
if ($FailedAPIs.Count -eq 0) {
Write-LogOk "所有接口测试通过"
return $true
}
else {
Write-LogWarn "部分接口测试失败"
return $false
}
}
# ============================================================================
# 系统授权函数
# ============================================================================
function Invoke-SystemAuthorization {
Write-LogStep "步骤7: 系统授权"
Write-LogWarn "系统授权需要访问Web界面完成,请按以下步骤操作:"
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "系统授权操作步骤" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "1. 访问维护平台: https://${ServerIP}/#/LoginConfig"
Write-Host "2. 输入验证码: csba"
Write-Host "3. 上传授权文件"
Write-Host " 授权文件路径: $($DeployConfig[$Architecture].LicenseFile)"
Write-Host "4. 完成授权操作"
Write-Host "========================================`n" -ForegroundColor Cyan
$Response = Read-Host "是否已完成系统授权?(y/n)"
if ($Response -eq 'y' -or $Response -eq 'Y') {
Write-LogOk "系统授权已完成"
$Global:DeployResults.Authorization = "已完成"
return $true
}
else {
Write-LogWarn "系统授权未完成"
$Global:DeployResults.Authorization = "未完成"
return $false
}
}
# ============================================================================
# 创建管理员函数
# ============================================================================
function New-CompanyAdmin {
Write-LogStep "步骤8: 创建公司管理员"
Write-LogWarn "创建管理员需要访问Web界面完成,请按以下步骤操作:"
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "创建公司管理员操作步骤" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "1. 访问后台地址: https://${ServerIP}/#/LoginAdmin"
Write-Host "2. 按照部署文档第四章创建公司管理员"
Write-Host "3. 完成用户创建操作"
Write-Host "========================================`n" -ForegroundColor Cyan
$Response = Read-Host "是否已创建公司管理员?(y/n)"
if ($Response -eq 'y' -or $Response -eq 'Y') {
Write-LogOk "公司管理员创建完成"
$Global:DeployResults.AdminCreated = "已完成"
return $true
}
else {
Write-LogWarn "公司管理员未创建"
$Global:DeployResults.AdminCreated = "未完成"
return $false
}
}
# ============================================================================
# 生成部署报告
# ============================================================================
function New-DeployReport {
Write-LogStep "步骤9: 生成部署报告"
$Timestamp = Get-Date -Format "yyyy_MM_dd_HHmmss"
$ReportFileName = "${ServerIP}_部署报告_${Timestamp}.md"
$ReportFilePath = Join-Path $ReportsDir $ReportFileName
$ReportContent = @"
# 新统一平台部署报告
## 基本信息
- 服务器IP: $ServerIP
- 架构类型: $Architecture
- 部署时间: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
## 部署结果
### 1. SSH连接
- 状态: $($Global:DeployResults.Connection)
### 2. 部署包上传
- 状态: $($Global:DeployResults.PackageUpload)
### 3. 部署执行
- 状态: $($Global:DeployResults.DeployExecution)
$(if ($Global:DeployResults.DeployLog) {
"- 部署日志: $($Global:DeployResults.DeployLog)"
})
### 4. 容器状态
"@
if ($Global:DeployResults.ContainerStatus -is [hashtable]) {
foreach ($Container in $Global:DeployResults.ContainerStatus.Keys) {
$ReportContent += "`n- $Container : $($Global:DeployResults.ContainerStatus[$Container])"
}
}
$ReportContent += @"
### 5. 服务日志
"@
if ($Global:DeployResults.ServiceLogs -is [hashtable]) {
foreach ($Log in $Global:DeployResults.ServiceLogs.Keys) {
$ReportContent += "`n- $Log : $($Global:DeployResults.ServiceLogs[$Log])"
}
}
$ReportContent += @"
### 6. 接口测试
"@
if ($Global:DeployResults.APITests -is [hashtable]) {
foreach ($API in $Global:DeployResults.APITests.Keys) {
$ReportContent += "`n- $API : $($Global:DeployResults.APITests[$API])"
}
}
$ReportContent += @"
### 7. 系统授权
- 状态: $($Global:DeployResults.Authorization)
### 8. 管理员创建
- 状态: $($Global:DeployResults.AdminCreated)
## 系统访问地址
- 前台地址: https://${ServerIP}/
- 维护地址: https://${ServerIP}/#/LoginConfig
- 后台地址: https://${ServerIP}/#/LoginAdmin
## 执行日志
"@
$ReportContent += $Global:ExecutionLog -join "`n"
$ReportContent += @"
---
报告生成时间: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
"@
try {
$ReportContent | Out-File -FilePath $ReportFilePath -Encoding UTF8 -Force
Write-LogOk "部署报告已生成: $ReportFilePath"
return $ReportFilePath
}
catch {
Write-LogError "报告生成失败: $_"
return $null
}
}
# ============================================================================
# 主函数
# ============================================================================
function Main {
# 记录开始时间
$StartTime = Get-Date
# 打印欢迎信息
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "新统一平台远程自动化部署脚本" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "目标服务器: ${ServerIP} (${Architecture})"
Write-Host "开始时间: $($StartTime.ToString('yyyy-MM-dd HH:mm:ss'))"
Write-Host "========================================`n" -ForegroundColor Cyan
# 初始化部署结果
$Global:DeployResults = @{
Connection = ""
PackageUpload = ""
DeployExecution = ""
ContainerStatus = @{}
ServiceLogs = @{}
APITests = @{}
Authorization = ""
AdminCreated = ""
}
try {
# 步骤1: 测试SSH连接
if (-not (Test-SSHConnection)) {
Write-LogError "SSH连接失败,部署终止"
New-DeployReport
return $false
}
# 步骤2: 上传部署包
if (-not (Upload-DeployPackage)) {
Write-LogError "部署包上传失败,部署终止"
New-DeployReport
return $false
}
# 步骤3: 执行部署脚本
if (-not (Invoke-DeployScript)) {
Write-LogError "部署脚本执行失败,继续检查服务状态..."
}
# 步骤4: 检查容器状态
Test-ContainerStatus
# 步骤5: 检查服务日志
Test-ServiceLogs
# 步骤6: 测试服务接口
Test-APIEndpoints
# 步骤7: 系统授权
Invoke-SystemAuthorization
# 步骤8: 创建管理员
New-CompanyAdmin
# 步骤9: 生成报告
$ReportPath = New-DeployReport
# 打印完成信息
$EndTime = Get-Date
$Duration = $EndTime - $StartTime
Write-Host "`n========================================" -ForegroundColor Green
Write-Host "部署完成" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host "结束时间: $($EndTime.ToString('yyyy-MM-dd HH:mm:ss'))"
Write-Host "总耗时: $($Duration.ToString('hh:mm:ss'))"
if ($ReportPath) {
Write-Host "报告位置: $ReportPath"
}
Write-Host "========================================`n" -ForegroundColor Green
return $true
}
catch {
Write-LogError "程序执行出错: $_"
New-DeployReport
return $false
}
}
# 检查plink.exe是否存在
if (-not (Test-Path $Global:PlinkPath)) {
Write-Host "错误: 找不到 plink.exe" -ForegroundColor Red
Write-Host "请从 https://the.earth.li/~sgtatham/putty/latest/w64/plink.exe 下载" -ForegroundColor Yellow
Write-Host "并将 plink.exe 放在脚本同目录下" -ForegroundColor Yellow
exit 1
}
# 执行主函数
Main
#!/bin/bash
# ============================================================================
# Remote Automated Deployment Script - New Unified Platform
# Purpose: Automatically complete the deployment of the new unified platform
# Author: Automation Operations Team
# Created: 2026-05-14
# ============================================================================
# Configuration
SERVER_IP="192.168.5.52"
SSH_PORT="22"
USERNAME="root"
PASSWORD="Ubains@123"
ARCHITECTURE="X86"
# Network share paths (for reference)
DEPLOY_SHARE_X86="\\\\192.168.9.9\\发布版本\\03服务器部署\\临时使用-新统一平台\\X86部署包\\全量版"
LICENSE_SHARE_X86="\\\\192.168.9.9\\发布版本\\03服务器部署\\临时使用-新统一平台\\测试授权文件-请勿使用\\5.52授权文件\\license.zip"
# Script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGES_DIR="$SCRIPT_DIR/packages"
REPORTS_DIR="$SCRIPT_DIR/reports"
TEMP_DIR="$SCRIPT_DIR/temp"
# SSH tools
PLINK="$SCRIPT_DIR/plink.exe"
PSCP="$SCRIPT_DIR/pscp.exe"
# Create directories
mkdir -p "$PACKAGES_DIR" "$REPORTS_DIR" "$TEMP_DIR"
# Log file
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="$REPORTS_DIR/deploy_${TIMESTAMP}.log"
# ============================================================================
# Logging Functions
# ============================================================================
log_info() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1"
echo "$msg" | tee -a "$LOG_FILE"
}
log_warn() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $1"
echo "$msg" | tee -a "$LOG_FILE"
}
log_error() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1"
echo "$msg" | tee -a "$LOG_FILE"
}
log_ok() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] [OK] $1"
echo "$msg" | tee -a "$LOG_FILE"
}
log_step() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] [STEP] $1"
echo "$msg" | tee -a "$LOG_FILE"
}
# ============================================================================
# SSH Functions
# ============================================================================
ssh_command() {
local cmd="$1"
local timeout="${2:-300}"
"$PLINK" -pw "$PASSWORD" -P "$SSH_PORT" -timeout "$timeout" "${USERNAME}@${SERVER_IP}" "$cmd" 2>&1
return $?
}
test_ssh_connection() {
log_step "Step 1: Testing SSH connection"
log_info "Connecting to server ${SERVER_IP}:${SSH_PORT}..."
for i in {1..3}; do
result=$(ssh_command "echo 'connection_ok'" 30)
if echo "$result" | grep -q "connection_ok"; then
log_ok "Connection successful"
return 0
else
log_warn "Connection failed, retrying ($i/3)..."
sleep 2
fi
done
log_error "Connection failed after 3 attempts"
return 1
}
# ============================================================================
# Deployment Functions
# ============================================================================
upload_deploy_package() {
log_step "Step 2: Upload deployment package"
# Check if deploy package is available locally or on network share
log_warn "Deployment package should be prepared manually"
log_info "Network share path: $DEPLOY_SHARE_X86"
log_info ""
log_info "Please copy the deployment package to: $PACKAGES_DIR"
log_info "Or ensure the package is already on the server at: /home/deploy"
read -p "Press Enter to continue after package is ready..."
# Create deployment directory on server
log_info "Creating deployment directory on server..."
result=$(ssh_command "mkdir -p /home/deploy && echo 'created'")
if echo "$result" | grep -q "created"; then
log_ok "Deployment directory created"
else
log_error "Failed to create deployment directory"
return 1
fi
return 0
}
execute_deploy_script() {
log_step "Step 3: Execute deployment script"
# Find deployment script on server
log_info "Searching for deployment scripts..."
result=$(ssh_command "find /home/deploy -name '*.sh' -type f 2>/dev/null | head -20")
if [ -z "$result" ]; then
log_error "No deployment script found on server"
log_info "Please upload the deployment script manually to /home/deploy"
return 1
fi
log_info "Found deployment scripts:"
echo "$result" | while read -r line; do
echo " - $line"
done
# Find main deployment script
main_script=$(echo "$result" | grep -E "(auto_deploy|deploy|install|setup)" | grep -v -E "\.(bak|backup|old)" | head -1)
if [ -z "$main_script" ]; then
main_script=$(echo "$result" | head -1)
fi
log_info "Selected main script: $main_script"
# Make script executable
log_info "Setting execute permissions..."
ssh_command "chmod +x '$main_script'" > /dev/null
# Execute deployment script
log_warn "Starting deployment script, estimated time: 40 minutes..."
log_info "Deployment output will be displayed..."
# Execute deployment with long timeout
ssh_command "cd /home/deploy && bash '$main_script' 2>&1" 3600 | tee -a "$LOG_FILE"
local exit_code=${PIPESTATUS[0]}
if [ $exit_code -eq 0 ]; then
log_ok "Deployment script executed successfully"
return 0
else
log_error "Deployment script failed with exit code: $exit_code"
return 1
fi
}
check_container_status() {
log_step "Step 4: Check container status"
# Check if Docker is running
result=$(ssh_command "docker ps --format 'table {{.Names}}\t{{.Status}}' 2>/dev/null")
if [ $? -ne 0 ]; then
log_error "Docker is not running or not accessible"
return 1
fi
echo ""
echo "========== Container Status =========="
echo "$result"
echo "========== Container Status End =========="
echo ""
# Check required containers
local required_containers=("ujava" "upython" "uredis" "umysql" "uemqx")
local all_ok=true
for container in "${required_containers[@]}"; do
result=$(ssh_command "docker inspect -f '{{.State.Running}}' $container 2>/dev/null || echo 'not_found'")
if echo "$result" | grep -q "true"; then
log_ok "$container: Running"
elif echo "$result" | grep -q "false"; then
log_warn "$container: Stopped"
all_ok=false
else
log_error "$container: Not found"
all_ok=false
fi
done
if [ "$all_ok" = true ]; then
log_ok "All required containers are running"
return 0
else
log_warn "Some containers are not running properly"
return 1
fi
}
check_service_logs() {
log_step "Step 5: Check service logs"
# Check external API service log
log_info "Checking external API service log..."
result=$(ssh_command "tail -100 /data/services/api/java-meeting/java-meeting-extapi/logs/ubains-INFO-AND-ERROR.log 2>/dev/null || echo 'log_not_found'")
if echo "$result" | grep -q "SYSTEMVERSION.*target_api_integration"; then
log_ok "External API service log is normal (version information detected)"
elif echo "$result" | grep -q "log_not_found"; then
log_warn "External API service log file not found"
else
log_warn "External API service log does not contain version information, waiting 10 minutes to retry..."
# Wait 10 minutes
for i in {1..10}; do
echo "Waiting... ($i/10 minutes)"
sleep 60
done
# Retry check
result=$(ssh_command "tail -100 /data/services/api/java-meeting/java-meeting-extapi/logs/ubains-INFO-AND-ERROR.log 2>/dev/null")
if echo "$result" | grep -q "SYSTEMVERSION"; then
log_ok "External API service log is normal (version information detected after retry)"
else
log_error "External API service log is abnormal (no version information after 10 minutes)"
fi
fi
return 0
}
test_api_endpoints() {
log_step "Step 6: Test service endpoints"
# Define API tests
local apis=(
"ExtAPI|https://${SERVER_IP}/exapi/message/getMsgPageList|A0076"
"Meeting|https://${SERVER_IP}/meetingV3/api/systemConfiguration/globalConfig?companyNumber=CN-SZ-00-0201|A0078"
"Monitor|https://${SERVER_IP}/monitor/api2/api/servermonitor/|40000014"
"Voice|https://${SERVER_IP}/voice/api/iflytek/roommaster?company_id=1&user_id=8&company_secret=57d00f9f-020f-5f1f-b788-55fae843bceb&getall=1|40000003"
)
local all_ok=true
for api_test in "${apis[@]}"; do
IFS='|' read -r api_name url expected <<< "$api_test"
log_info "Testing $api_name endpoint..."
# Use curl to test endpoint (ignore SSL certificate)
result=$(ssh_command "curl -k '$url' 2>/dev/null" 60)
if echo "$result" | grep -q "$expected"; then
log_ok "$api_name endpoint is normal (returns expected authentication error)"
elif echo "$result" | grep -q "An error occurred\|nginx"; then
log_error "$api_name endpoint is abnormal (returns nginx error page)"
# Retry mechanism
local retry_success=false
for retry in {1..5}; do
log_warn "Retry $retry..."
sleep 30
result=$(ssh_command "curl -k '$url' 2>/dev/null" 60)
if echo "$result" | grep -q "$expected"; then
log_ok "$api_name endpoint is normal (successful after retry $retry)"
retry_success=true
break
fi
done
if [ "$retry_success" = false ]; then
all_ok=false
fi
else
log_warn "$api_name endpoint returned unknown response"
fi
done
if [ "$all_ok" = true ]; then
log_ok "All API endpoints tested successfully"
return 0
else
log_warn "Some API endpoints failed testing"
return 1
fi
}
system_authorization() {
log_step "Step 7: System Authorization"
echo ""
echo "========================================"
echo "System Authorization Steps"
echo "========================================"
echo "1. Visit maintenance platform: https://${SERVER_IP}/#/LoginConfig"
echo "2. Enter verification code: csba"
echo "3. Upload license file"
echo " License file path: $LICENSE_SHARE_X86"
echo "4. Complete authorization"
echo "========================================"
echo ""
read -p "Have you completed the system authorization? (y/n) " response
if [ "$response" = "y" ] || [ "$response" = "Y" ]; then
log_ok "System authorization completed"
return 0
else
log_warn "System authorization not completed"
return 1
fi
}
create_company_admin() {
log_step "Step 8: Create Company Administrator"
echo ""
echo "========================================"
echo "Create Company Administrator Steps"
echo "========================================"
echo "1. Visit backend address: https://${SERVER_IP}/#/LoginAdmin"
echo "2. Follow deployment documentation Chapter 4 to create company administrator"
echo "3. Complete user creation"
echo "========================================"
echo ""
read -p "Have you created the company administrator? (y/n) " response
if [ "$response" = "y" ] || [ "$response" = "Y" ]; then
log_ok "Company administrator created"
return 0
else
log_warn "Company administrator not created"
return 1
fi
}
generate_report() {
log_step "Step 9: Generate deployment report"
local report_file="$REPORTS_DIR/${SERVER_IP}_deployment_report_${TIMESTAMP}.md"
cat > "$report_file" << EOF
# New Unified Platform Deployment Report
## Basic Information
- Server IP: $SERVER_IP
- Architecture: $ARCHITECTURE
- Deployment Time: $(date '+%Y-%m-%d %H:%M:%S')
## System Access Addresses
- Frontend Address: https://${SERVER_IP}/
- Maintenance Address: https://${SERVER_IP}/#/LoginConfig
- Backend Address: https://${SERVER_IP}/#/LoginAdmin
---
Report Generated Time: $(date '+%Y-%m-%d %H:%M:%S')
EOF
log_ok "Deployment report generated: $report_file"
echo ""
echo "Report location: $report_file"
return 0
}
# ============================================================================
# Main Function
# ============================================================================
main() {
local start_time=$(date +%s)
echo ""
echo "========================================"
echo "New Unified Platform Remote Automated Deployment Script"
echo "========================================"
echo "Target Server: ${SERVER_IP} (${ARCHITECTURE})"
echo "Start Time: $(date '+%Y-%m-%d %H:%M:%S')"
echo "========================================"
echo ""
local deploy_success=true
# Step 1: Test SSH connection
if ! test_ssh_connection; then
log_error "SSH connection failed, deployment terminated"
generate_report
return 1
fi
# Step 2: Upload deployment package
if ! upload_deploy_package; then
log_error "Deployment package preparation failed, continuing with deployment..."
fi
# Step 3: Execute deployment script
if ! execute_deploy_script; then
log_error "Deployment script execution failed, continuing with service checks..."
fi
# Step 4: Check container status
check_container_status
# Step 5: Check service logs
check_service_logs
# Step 6: Test API endpoints
test_api_endpoints
# Step 7: System authorization
system_authorization
# Step 8: Create company administrator
create_company_admin
# Step 9: Generate report
generate_report
# Print completion message
local end_time=$(date +%s)
local duration=$((end_time - start_time))
local hours=$((duration / 3600))
local minutes=$(((duration % 3600) / 60))
local seconds=$((duration % 60))
echo ""
echo "========================================"
echo "Deployment Completed"
echo "========================================"
echo "End Time: $(date '+%Y-%m-%d %H:%M:%S')"
printf "Total Duration: %02d:%02d:%02d\n" $hours $minutes $seconds
echo "========================================"
echo ""
return 0
}
# Check if plink.exe exists
if [ ! -f "$PLINK" ]; then
echo "Error: plink.exe not found"
echo "Please download from: https://the.earth.li/~sgtatham/putty/latest/w64/plink.exe"
echo "And place plink.exe in the script directory"
exit 1
fi
# Execute main function
main
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
自动处理部署脚本的交互式提示
"""
import sys
import os
import time
import subprocess
from datetime import datetime
def run_deployment_auto():
"""使用plink和yes命令自动运行部署"""
print("=" * 60)
print("自动处理交互式提示的部署脚本")
print("=" * 60)
print(f"开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print()
plink_path = r"E:\GithubData\ubains-module-test\AuxiliaryTool\ScriptTool\RemoteDeploy\plink.exe"
# 首先检查并终止现有进程
print("1. 检查并清理现有进程...")
check_cmd = [plink_path, "-pw", "Ubains@123", "-P", "22",
"root@192.168.5.52", "pkill -9 -f new_auto.sh; sleep 2"]
result = subprocess.run(check_cmd, capture_output=True, text=True,
creationflags=subprocess.CREATE_NO_WINDOW)
print(" 已清理现有进程")
# 创建部署命令脚本
print("2. 准备部署命令...")
# 使用yes命令自动响应y/n提示,然后进入部署目录并运行脚本
deploy_commands = """
cd /data/offline_auto_unifiedPlatform
# 使用yes命令自动响应所有的y/n提示
yes y | ./new_auto.sh
"""
# 运行部署
print("3. 开始部署(使用yes命令自动响应所有提示)...")
print(" 这将需要大约40分钟时间...")
print()
deploy_cmd = [plink_path, "-pw", "Ubains@123", "-P", "22",
"root@192.168.5.52", deploy_commands]
# 启动部署进程
process = subprocess.Popen(deploy_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
creationflags=subprocess.CREATE_NO_WINDOW)
# 监控部署过程
start_time = time.time()
max_time = 2400 # 40分钟
last_output = ""
output_count = 0
print("开始监控部署过程...")
print("-" * 60)
while time.time() - start_time < max_time:
try:
# 检查进程状态
if process.poll() is not None:
print("\n[完成] 部署进程已结束")
break
# 读取输出
try:
# 非阻塞读取
import msvcrt
if msvcrt.kbhit():
# 用户按了键,可以提前退出
if msvcrt.getch() == b'q':
print("\n用户取消部署")
process.terminate()
break
except:
pass
# 每60秒输出一次进度
elapsed = int(time.time() - start_time)
if elapsed % 60 == 0 and elapsed > 0 and elapsed != output_count:
output_count = elapsed
print(f"[进度] 部署进行中... 已用时: {int(elapsed/60)}分钟")
# 检查容器状态
check_cmd = [plink_path, "-pw", "Ubains@123", "-P", "22",
"root@192.168.5.52", "docker ps | wc -l"]
try:
check_result = subprocess.run(check_cmd, capture_output=True,
text=True, timeout=10,
creationflags=subprocess.CREATE_NO_WINDOW)
container_count = check_result.stdout.strip()
if container_count and int(container_count) > 1:
print(f"[容器] 已启动 {int(container_count)-1} 个容器")
except:
pass
time.sleep(10)
except KeyboardInterrupt:
print("\n用户中断部署")
process.terminate()
break
except Exception as e:
print(f"[WARN] 监控出错: {str(e)}")
time.sleep(10)
# 获取最终输出
print()
print("=" * 60)
print("部署完成检查")
print("=" * 60)
# 检查容器状态
final_check = [plink_path, "-pw", "Ubains@123", "-P", "22",
"root@192.168.5.52",
"docker ps --format 'table {{.Names}}\t{{.Status}}'"]
try:
final_result = subprocess.run(final_check, capture_output=True,
text=True, timeout=30,
creationflags=subprocess.CREATE_NO_WINDOW)
print("\n最终容器状态:")
print(final_result.stdout)
container_count = final_result.stdout.strip().count('\n') - 1
print(f"\n运行中的容器数量: {container_count}")
if container_count >= 5:
print("\n[SUCCESS] 部署成功完成!")
print("\n后续步骤:")
print("1. 系统授权: https://192.168.5.52/#/LoginConfig")
print(" 账号: superadmin / Ubains@1357")
print(" 验证码: csba")
print("\n2. 创建管理员: 为'自动化'公司创建admin用户")
return 0
else:
print("\n[WARN] 部署可能未完全完成")
return 1
except Exception as e:
print(f"\n[ERROR] 最终检查失败: {str(e)}")
return 1
if __name__ == '__main__':
try:
sys.exit(run_deployment_auto())
except Exception as e:
print(f"[ERROR] 部署失败: {str(e)}")
import traceback
traceback.print_exc()
sys.exit(1)
# Simple Remote Deployment Script using Windows OpenSSH
# Author: Automation Team
# Date: 2026-05-14
param(
[string]$ServerIP = "192.168.5.52",
[string]$Username = "root",
[string]$Password = "Ubains@123",
[int]$SSHPort = 22
)
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$ReportsDir = Join-Path $ScriptDir "reports"
$LogFile = Join-Path $ReportsDir "deploy_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
# Create reports directory
if (-not (Test-Path $ReportsDir)) {
New-Item -ItemType Directory -Path $ReportsDir -Force | Out-Null
}
# Logging function
function Write-Log {
param([string]$Message, [string]$Level = "INFO")
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogMessage = "[$Timestamp] [$Level] $Message"
Write-Host $LogMessage
Add-Content -Path $LogFile -Value $LogMessage
}
# SSH command function using plink with host key auto-accept
function Invoke-SSHCommand {
param([string]$Command, [int]$Timeout = 300)
$PlinkPath = Join-Path $ScriptDir "plink.exe"
# Create temporary plink session to accept host key
$Args = @(
"-pw", $Password,
"-P", $SSHPort,
"-hostkey",
'*',
"$Username@$ServerIP",
$Command
)
$Output = & $PlinkPath $Args 2>&1
return $Output
}
Write-Log "========================================"
Write-Log "New Unified Platform Deployment Script"
Write-Log "Target Server: ${ServerIP}"
Write-Log "========================================"
# Test SSH connection
Write-Log "Testing SSH connection..."
$TestResult = Invoke-SSHCommand -Command "echo 'connection_ok'"
if ($TestResult -match "connection_ok") {
Write-Log "SSH connection successful" "OK"
# Get server information
Write-Log "Getting server information..."
$SystemInfo = Invoke-SSHCommand -Command "uname -a"
Write-Log "Server OS: $SystemInfo"
# Check if /data/services exists (new platform)
$PlatformCheck = Invoke-SSHCommand -Command "test -d /data/services && echo 'new' || echo 'old'"
Write-Log "Platform type: $PlatformCheck"
# Check Docker status
Write-Log "Checking Docker status..."
$DockerCheck = Invoke-SSHCommand -Command "docker ps --format 'table {{.Names}}\t{{.Status}}' 2>&1"
if ($LASTEXITCODE -eq 0) {
Write-Log "Docker is running"
Write-Host "`n========== Container Status =========="
Write-Host $DockerCheck
Write-Host "========== Container Status End ==========`n"
} else {
Write-Log "Docker is not running or not accessible" "WARN"
}
} else {
Write-Log "SSH connection failed" "ERROR"
Write-Log "Error: $TestResult" "ERROR"
Write-Log ""
Write-Log "Please ensure:" "INFO"
Write-Log "1. Server IP is correct: $ServerIP" "INFO"
Write-Log "2. SSH port is open: $SSHPort" "INFO"
Write-Log "3. Username and password are correct" "INFO"
Write-Log "4. Server is reachable from this machine" "INFO"
}
Write-Log "========================================"
Write-Log "Deployment script completed"
Write-Log "Log file: $LogFile"
Write-Log "========================================"
# Remote Deployment Script using Windows OpenSSH
# Author: Automation Team
# Date: 2026-05-14
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$ReportsDir = Join-Path $ScriptDir "reports"
if (-not (Test-Path $ReportsDir)) {
New-Item -ItemType Directory -Path $ReportsDir -Force | Out-Null
}
$LogFile = Join-Path $ReportsDir "deploy_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
function Write-Log {
param([string]$Message, [string]$Color = "White")
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogMessage = "[$Timestamp] $Message"
Write-Host $LogMessage -ForegroundColor $Color
Add-Content -Path $LogFile -Value $LogMessage
}
Write-Log "========================================" "Cyan"
Write-Log "New Unified Platform Deployment Script" "Cyan"
Write-Log "========================================" "Cyan"
# Configuration
$ServerIP = "192.168.5.52"
$Username = "root"
$Password = "Ubains@123"
$SSHPort = 22
# Use plink.exe
$PlinkPath = Join-Path $ScriptDir "plink.exe"
Write-Log "Target Server: ${ServerIP}:${SSHPort}"
Write-Log ""
# Step 1: Accept host key
Write-Log "Step 1: Establishing SSH connection (accepting host key)..." "Yellow"
# Create a process to start plink and automatically answer 'y' to host key prompt
$StartInfo = New-Object System.Diagnostics.ProcessStartInfo
$StartInfo.FileName = $PlinkPath
$StartInfo.Arguments = "-pw $Password -P $SSHPort $Username@${ServerIP} echo 'connection_ok'"
$StartInfo.UseShellExecute = $false
$StartInfo.RedirectStandardInput = $true
$StartInfo.RedirectStandardOutput = $true
$StartInfo.RedirectStandardError = $true
$StartInfo.CreateNoWindow = $true
$Process = New-Object System.Diagnostics.Process
$Process.StartInfo = $StartInfo
$Process.Start() | Out-Null
# Automatically answer 'y' to any prompts
$Process.StandardInput.WriteLine("y")
$Process.StandardInput.Close()
# Wait for process to complete
$Process.WaitForExit(30000)
$Output = $Process.StandardOutput.ReadToEnd()
$Error = $Process.StandardError.ReadToEnd()
if ($Output -match "connection_ok") {
Write-Log "SSH connection established successfully!" "Green"
# Step 2: Get server information
Write-Log ""
Write-Log "Step 2: Getting server information..." "Cyan"
$StartInfo.Arguments = "-pw $Password -P $SSHPort $Username@${ServerIP} uname -a"
$Process2 = New-Object System.Diagnostics.Process
$Process2.StartInfo = $StartInfo
$Process2.Start() | Out-Null
$Process2.WaitForExit(30000)
$ServerInfo = $Process2.StandardOutput.ReadToEnd()
Write-Log "Server OS: $ServerInfo" "Green"
# Step 3: Check Docker status
Write-Log ""
Write-Log "Step 3: Checking Docker status..." "Cyan"
$StartInfo.Arguments = "-pw $Password -P $SSHPort $Username@${ServerIP} docker ps --format 'table {{.Names}}\t{{.Status}}'"
$Process3 = New-Object System.Diagnostics.Process
$Process3.StartInfo = $StartInfo
$Process3.Start() | Out-Null
$Process3.WaitForExit(30000)
$DockerOutput = $Process3.StandardOutput.ReadToEnd()
if ($DockerOutput) {
Write-Log "Docker is running" "Green"
Write-Host ""
Write-Host "========== Container Status ==========" -ForegroundColor Cyan
Write-Host $DockerOutput
Write-Host "========== Container Status End ==========" -ForegroundColor Cyan
Write-Host ""
} else {
Write-Log "Docker is not running or not accessible" "Yellow"
}
Write-Log ""
Write-Log "========================================" "Green"
Write-Log "Connection test completed successfully!" "Green"
Write-Log "========================================" "Green"
} else {
Write-Log "SSH connection failed" "Red"
Write-Log "Error: $Error" "Red"
Write-Log ""
Write-Log "Possible reasons:" "Yellow"
Write-Log "1. Server IP is incorrect" "Yellow"
Write-Log "2. SSH port is closed" "Yellow"
Write-Log "3. Username or password is incorrect" "Yellow"
Write-Log "4. Server is not reachable" "Yellow"
}
Write-Log ""
Write-Log "Log file: $LogFile"
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
远程自动化部署脚本 - 完整流程
支持SSH交互式部署、Web界面授权和用户创建
"""
import time
import os
import sys
from datetime import datetime
import traceback
# SSH和交互处理
import paramiko
import threading
import time
# Web自动化
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.common.keys import Keys
# HTTP请求
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
# 禁用SSL警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
class RemoteDeploymentAutomation:
"""远程自动化部署类"""
def __init__(self, host, username, password, license_path):
self.host = host
self.username = username
self.password = password
self.license_path = license_path
self.ssh_client = None
self.ssh_shell = None
self.driver = None
self.log_prefix = f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}]"
def log(self, message, level="INFO"):
"""日志输出"""
prefix = {"INFO": "[OK]", "ERROR": "[ERROR]", "WARN": "[WARN]", "DEBUG": "[DEBUG]"}
try:
print(f"{self.log_prefix} {prefix.get(level, '[INFO]')} {message}")
except UnicodeEncodeError:
# 处理编码错误,使用ASCII安全输出
safe_message = message.encode('gbk', errors='ignore').decode('gbk')
print(f"{self.log_prefix} {prefix.get(level, '[INFO]')} {safe_message}")
def connect_ssh(self):
"""连接SSH(使用paramiko)"""
try:
self.log(f"连接SSH服务器: {self.username}@{self.host}")
self.ssh_client = paramiko.SSHClient()
self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.ssh_client.connect(self.host, username=self.username, password=self.password, timeout=30)
self.log("SSH连接成功")
return True
except Exception as e:
self.log(f"SSH连接失败: {str(e)}", "ERROR")
return False
def connect_ssh_interactive(self):
"""连接SSH交互式会话(使用paramiko的invoke_shell)"""
try:
# 确保SSH客户端已连接
if not self.ssh_client or not self.ssh_client.get_transport() or not self.ssh_client.get_transport().is_active():
self.log("SSH客户端未连接,先建立连接", "WARN")
if not self.connect_ssh():
return False
self.log(f"创建SSH交互式会话: {self.username}@{self.host}")
self.ssh_shell = self.ssh_client.invoke_shell()
time.sleep(1)
# 等待shell就绪
output = ""
while True:
try:
chunk = self.ssh_shell.recv(1024).decode('utf-8', errors='ignore')
if not chunk:
break
output += chunk
if '#' in output or '$' in output:
break
except:
break
self.log("SSH交互式会话创建成功")
return True
except Exception as e:
self.log(f"SSH交互式连接失败: {str(e)}", "ERROR")
return False
def run_deployment_script_interactive(self):
"""运行部署脚本(处理whiptail交互式菜单)"""
try:
self.log("开始执行部署脚本(交互式)")
# 确保shell连接可用
if not self.ssh_shell:
if not self.connect_ssh_interactive():
return False
# 切换到部署目录
self.log("切换到部署目录...")
self.ssh_shell.send("cd /data/offline_auto_unifiedPlatform\n")
time.sleep(2)
# 清空缓冲区
try:
while self.ssh_shell.recv_ready():
self.ssh_shell.recv(1024)
except:
pass
# 运行部署脚本
self.log("启动部署脚本...")
self.ssh_shell.send("./new_auto.sh\n")
time.sleep(3)
# 等待菜单出现并选择"全部系统"
self.log("等待部署菜单...")
self.log("提示: 如果出现whiptail菜单,请手动选择'全部系统'选项")
self.log(" 通常按Enter键选择默认选项或按空格键选中后按Enter确认")
# 等待菜单出现(最长等待10分钟)
max_wait = 600
start_time = time.time()
menu_detected = False
output_buffer = ""
while time.time() - start_time < max_wait:
try:
if self.ssh_shell.recv_ready():
chunk = self.ssh_shell.recv(4096).decode('utf-8', errors='ignore')
output_buffer += chunk
# 检测whiptail菜单
if 'whiptail' in output_buffer or '选择系统' in output_buffer or '全部系统' in output_buffer:
if not menu_detected:
self.log("检测到部署菜单")
menu_detected = True
# 尝试自动选择"全部系统"
self.log("尝试自动选择'全部系统'(发送回车)")
self.ssh_shell.send("\n")
time.sleep(2)
# 检测是否开始部署
if '开始部署' in output_buffer or '正在部署' in output_buffer or 'deploying' in output_buffer.lower():
self.log("检测到部署开始,菜单选择成功")
break
time.sleep(1)
# 每30秒输出一次等待状态
elapsed = int(time.time() - start_time)
if elapsed % 30 == 0 and elapsed > 0:
self.log(f"等待菜单中... 已等待: {elapsed}秒")
except Exception as e:
self.log(f"读取输出时出错: {str(e)}", "WARN")
time.sleep(1)
if not menu_detected:
self.log("未检测到明确菜单,可能脚本直接开始执行", "WARN")
# 等待部署完成(最长40分钟)
self.log("等待部署完成(预计40分钟)...")
self.log("监控部署进度...")
deployment_start = time.time()
max_deployment_time = 2400 # 40分钟
last_output = ""
while time.time() - deployment_start < max_deployment_time:
try:
if self.ssh_shell.recv_ready():
chunk = self.ssh_shell.recv(4096).decode('utf-8', errors='ignore')
last_output += chunk
# 检查部署完成标志
if '部署完成' in last_output or '部署成功' in last_output or 'deployment completed' in last_output.lower():
self.log("检测到部署完成标志")
break
# 检查错误
if 'error' in last_output.lower() and 'fatal' in last_output.lower():
self.log(f"检测到严重错误: {last_output[-500:]}", "ERROR")
# 每60秒输出一次进度
elapsed = int(time.time() - deployment_start)
if elapsed % 60 == 0 and elapsed > 0:
self.log(f"部署进行中... 已用时: {int(elapsed/60)}分钟/{int(max_deployment_time/60)}分钟")
time.sleep(5)
except Exception as e:
self.log(f"监控部署时出错: {str(e)}", "WARN")
time.sleep(5)
# 检查部署结果
self.log("检查容器状态...")
self.ssh_shell.send("docker ps --format 'table {{.Names}}\t{{.Status}}'\n")
time.sleep(3)
docker_output = ""
try:
while self.ssh_shell.recv_ready():
docker_output += self.ssh_shell.recv(4096).decode('utf-8', errors='ignore')
except:
pass
self.log(f"容器状态:\n{docker_output}")
return True
except Exception as e:
self.log(f"部署脚本执行失败: {str(e)}", "ERROR")
self.log(traceback.format_exc(), "DEBUG")
return False
def init_browser(self):
"""初始化浏览器"""
try:
self.log("初始化Chrome浏览器...")
options = ChromeOptions()
options.add_argument('--ignore-certificate-errors')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--disable-gpu')
self.driver = webdriver.Chrome(options=options)
self.driver.implicitly_wait(10)
self.log("浏览器初始化成功")
return True
except Exception as e:
self.log(f"浏览器初始化失败: {str(e)}", "ERROR")
return False
def close_browser(self):
"""关闭浏览器"""
if self.driver:
try:
self.driver.quit()
self.log("浏览器已关闭")
except:
pass
def system_authorization(self):
"""系统授权操作"""
try:
self.log("开始系统授权流程")
# 访问维护平台
self.log("访问维护平台: https://192.168.5.52/#/LoginConfig")
self.driver.get("https://192.168.5.52/#/LoginConfig")
time.sleep(3)
# 登录
self.log("登录维护平台...")
# 查找登录表单
try:
# 账号输入框
account_input = self.driver.find_element(By.CSS_SELECTOR, 'input[placeholder*="账号"]')
account_input.clear()
account_input.send_keys('superadmin')
self.log("输入账号: superadmin")
# 密码输入框
password_input = self.driver.find_element(By.CSS_SELECTOR, 'input[placeholder*="密码"]')
password_input.clear()
password_input.send_keys('Ubains@1357')
self.log("输入密码: *******")
# 验证码输入框
verify_input = self.driver.find_element(By.CSS_SELECTOR, 'input[placeholder*="验证码"]')
verify_input.clear()
verify_input.send_keys('csba')
self.log("输入验证码: csba")
# 点击登录按钮
login_btn = self.driver.find_element(By.CSS_SELECTOR, 'button')
login_btn.click()
self.log("点击登录按钮")
time.sleep(5)
except Exception as e:
self.log(f"登录操作失败: {str(e)}", "ERROR")
return False
# 检查是否登录成功
current_url = self.driver.current_url
self.log(f"当前URL: {current_url}")
# 上传授权文件
self.log("准备上传授权文件...")
time.sleep(2)
# 查找并点击上传按钮
upload_btn = WebDriverWait(self.driver, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, 'button'))
)
# 可能需要点击特定的上传按钮
buttons = self.driver.find_elements(By.CSS_SELECTOR, 'button')
for btn in buttons:
btn_text = btn.text
if '上传授权文件' in btn_text or '上传' in btn_text:
self.log(f"找到上传按钮: {btn_text}")
btn.click()
time.sleep(2)
break
# 处理可能出现的身份验证对话框
try:
# 检查是否有验证对话框
verify_dialog = self.driver.find_elements(By.CSS_SELECTOR, 'div[role="dialog"]')
if verify_dialog and '校验身份' in verify_dialog[0].text:
self.log("检测到身份验证对话框")
# 输入密码
pwd_inputs = self.driver.find_elements(By.CSS_SELECTOR, 'input[type="password"]')
if pwd_inputs:
pwd_inputs[0].send_keys('Ubains@1357')
self.log("输入验证密码")
# 输入验证码
verify_inputs = self.driver.find_elements(By.CSS_SELECTOR, 'input[placeholder*="验证码"]')
if verify_inputs:
verify_inputs[0].clear()
verify_inputs[0].send_keys('csba')
self.log("输入验证码: csba")
# 点击确定
confirm_btns = self.driver.find_elements(By.CSS_SELECTOR, 'button')
for btn in confirm_btns:
if '确定' in btn.text:
btn.click()
self.log("点击确定按钮")
break
time.sleep(3)
except:
pass
# 上传文件
self.log(f"上传授权文件: {self.license_path}")
# 查找文件上传input
file_inputs = self.driver.find_elements(By.CSS_SELECTOR, 'input[type="file"]')
if file_inputs:
file_inputs[0].send_keys(os.path.abspath(self.license_path))
self.log("授权文件已上传")
time.sleep(5)
else:
self.log("未找到文件上传输入框", "WARN")
self.log("系统授权流程完成")
return True
except Exception as e:
self.log(f"系统授权失败: {str(e)}", "ERROR")
self.log(traceback.format_exc(), "DEBUG")
return False
def create_company_admin(self):
"""创建公司管理员"""
try:
self.log("开始创建公司管理员")
# 导航到公司管理页面
self.log("导航到公司管理页面...")
self.driver.get("https://192.168.5.52/#/backend/backstage?backstage=%2Fbackstage%2F%23%2FBackend%2FAccount%2FCompany")
time.sleep(3)
# 查找"自动化"公司
self.log("查找'自动化'公司...")
# 等待表格加载
time.sleep(3)
# 查找包含"自动化"文字的行
try:
# 可能需要先登录后台
current_url = self.driver.current_url
if 'login' in current_url.lower():
self.log("需要重新登录后台")
# 登录后台
account_input = self.driver.find_element(By.CSS_SELECTOR, 'input[placeholder*="账号"]')
account_input.clear()
account_input.send_keys('superadmin')
password_input = self.driver.find_element(By.CSS_SELECTOR, 'input[placeholder*="密码"]')
password_input.send_keys('Ubains@1357')
verify_input = self.driver.find_element(By.CSS_SELECTOR, 'input[placeholder*="验证码"]')
verify_input.clear()
verify_input.send_keys('csba')
login_btn = self.driver.find_element(By.CSS_SELECTOR, 'button')
login_btn.click()
time.sleep(3)
# 重新导航到公司管理页面
self.driver.get("https://192.168.5.52/#/backend/backstage?backstage=%2Fbackstage%2F%23%2FBackend%2FAccount%2FCompany")
time.sleep(3)
# 查找所有公司行
company_elements = self.driver.find_elements(By.CSS_SELECTOR, 'tr')
automation_company = None
for company in company_elements:
company_text = company.text
if '自动化' in company_text and 'CN-MWQ-UBAINS' in company_text:
automation_company = company
self.log(f"找到'自动化'公司: CN-MWQ-UBAINS")
break
if automation_company:
# 点击"设置企业管理员"按钮
admin_buttons = automation_company.find_elements(By.CSS_SELECTOR, 'button')
for btn in admin_buttons:
if '设置企业管理员' in btn.text or '管理员' in btn.text:
btn.click()
self.log("点击'设置企业管理员'按钮")
time.sleep(2)
break
# 在弹出的对话框中输入admin
self.log("输入管理员用户名: admin")
admin_name_input = self.driver.find_element(By.CSS_SELECTOR, 'input[placeholder*="用户名称"]')
admin_name_input.clear()
admin_name_input.send_keys('admin')
# 点击确定按钮
confirm_buttons = self.driver.find_elements(By.CSS_SELECTOR, 'button')
for btn in confirm_buttons:
if '确定' in btn.text:
btn.click()
self.log("点击确定按钮创建管理员")
time.sleep(2)
break
self.log("公司管理员创建成功")
else:
self.log("未找到'自动化'公司", "WARN")
return True
except Exception as e:
self.log(f"创建管理员失败: {str(e)}", "ERROR")
self.log(traceback.format_exc(), "DEBUG")
return False
except Exception as e:
self.log(f"创建公司管理员失败: {str(e)}", "ERROR")
self.log(traceback.format_exc(), "DEBUG")
return False
def verify_deployment(self):
"""验证部署结果"""
try:
self.log("开始验证部署结果")
# API接口测试
api_tests = [
{
'name': '预定系统对外接口',
'url': 'https://192.168.5.52/exapi/message/getMsgPageList',
'expected': 'A0076'
},
{
'name': '预定系统对内接口',
'url': 'https://192.168.5.52/meetingV3/api/systemConfiguration/globalConfig?companyNumber=CN-SZ-00-0201',
'expected': 'A0078'
},
{
'name': '运维集控系统接口',
'url': 'https://192.168.5.52/monitor/api2/api/servermonitor/',
'expected': '40000014'
},
{
'name': '语音转录系统接口',
'url': 'https://192.168.5.52/voice/api/iflytek/roommaster?company_id=1&user_id=8&company_secret=57d00f9f-020f-5f1f-b788-55fae843bceb&getall=1',
'expected': '40000003'
}
]
results = []
for test in api_tests:
self.log(f"测试 {test['name']}...")
try:
resp = requests.get(test['url'], verify=False, timeout=10)
if test['expected'] in resp.text:
self.log(f"✅ {test['name']}: PASS (返回码: {test['expected']})")
results.append(True)
else:
self.log(f"⚠️ {test['name']}: UNEXPECTED RESPONSE", "WARN")
results.append(False)
except Exception as e:
self.log(f"❌ {test['name']}: REQUEST FAILED - {str(e)}", "ERROR")
results.append(False)
# 检查容器状态
self.log("检查容器状态...")
if self.ssh_shell:
self.ssh_shell.send('docker ps --format "table {{.Names}}\t{{.Status}}"\n')
time.sleep(2)
docker_output = ""
try:
while self.ssh_shell.recv_ready():
docker_output += self.ssh_shell.recv(4096).decode('utf-8', errors='ignore')
except:
pass
self.log(f"容器状态:\n{docker_output}")
success_count = sum(results)
total_count = len(results)
self.log(f"API测试结果: {success_count}/{total_count} 通过")
return success_count == total_count
except Exception as e:
self.log(f"验证部署失败: {str(e)}", "ERROR")
return False
def prepare_deployment_environment(self):
"""准备部署环境"""
try:
self.log("检查并准备部署环境...")
# 检查部署目录是否存在
stdin, stdout, stderr = self.ssh_client.exec_command('test -d /data/offline_auto_unifiedPlatform && echo "EXISTS" || echo "NOT_EXISTS"')
result = stdout.read().decode('utf-8', errors='ignore').strip()
if result == "NOT_EXISTS":
self.log("部署目录不存在,检查部署包...", "WARN")
# 检查部署包是否存在
stdin, stdout, stderr = self.ssh_client.exec_command('test -f /data/offline_auto_unifiedPlatform.tar.gz && echo "EXISTS" || echo "NOT_EXISTS"')
pkg_result = stdout.read().decode('utf-8', errors='ignore').strip()
if pkg_result == "EXISTS":
self.log("解压部署包(约8.5GB,可能需要几分钟)...")
# 使用后台任务解压
channel = self.ssh_client.invoke_shell()
channel.send("cd /data && tar -xzf offline_auto_unifiedPlatform.tar.gz\n")
# 等待解压完成
import time
max_wait = 600 # 10分钟
start_time = time.time()
while time.time() - start_time < max_wait:
time.sleep(5)
stdin, stdout, stderr = self.ssh_client.exec_command('test -d /data/offline_auto_unifiedPlatform && echo "EXISTS" || echo "NOT_EXISTS"')
result = stdout.read().decode('utf-8', errors='ignore').strip()
if result == "EXISTS":
self.log("部署包解压完成")
channel.close()
return True
self.log(f"解压进行中... 已用时: {int((time.time() - start_time)/60)}分钟")
channel.close()
self.log("解压超时", "ERROR")
return False
else:
self.log("部署包不存在", "ERROR")
return False
else:
self.log("部署目录已就绪")
return True
except Exception as e:
self.log(f"准备部署环境失败: {str(e)}", "ERROR")
return False
def run_full_deployment(self):
"""执行完整部署流程"""
try:
self.log("=" * 50)
self.log("开始远程自动化部署")
self.log("=" * 50)
self.log(f"目标服务器: {self.host}")
self.log(f"授权文件: {self.license_path}")
self.log("=" * 50)
# 0. 准备部署环境
self.log("\n[0/5] 准备部署环境...")
if not self.connect_ssh():
self.log("SSH连接失败,终止部署", "ERROR")
return False
if not self.prepare_deployment_environment():
self.log("准备部署环境失败", "ERROR")
return False
# 1. SSH连接和部署(复用现有SSH连接)
self.log("\n[1/5] 执行部署脚本...")
if not self.connect_ssh_interactive():
self.log("SSH交互式连接失败,终止部署", "ERROR")
return False
success = self.run_deployment_script_interactive()
if not success:
self.log("部署脚本执行失败", "ERROR")
return False
# 关闭SSH交互连接
if self.ssh_shell:
try:
self.ssh_shell.close()
except:
pass
# 关闭SSH连接
if self.ssh_client:
self.ssh_client.close()
# 2. 系统授权
self.log("\n[2/5] 系统授权...")
if not self.init_browser():
self.log("浏览器初始化失败", "ERROR")
return False
success = self.system_authorization()
if not success:
self.log("系统授权失败", "ERROR")
self.close_browser()
return False
# 3. 创建管理员
self.log("\n[3/5] 创建公司管理员...")
success = self.create_company_admin()
if not success:
self.log("创建管理员失败", "ERROR")
self.close_browser()
return False
# 4. 验证部署
self.log("\n[4/5] 验证部署...")
# 重新连接SSH进行验证
if self.connect_ssh_interactive():
self.verify_deployment()
# 5. 完成
self.log("\n[5/5] 部署流程完成")
self.log("=" * 50)
self.log("✅ 远程自动化部署完成!")
self.log("=" * 50)
return True
except Exception as e:
self.log(f"部署流程失败: {str(e)}", "ERROR")
self.log(traceback.format_exc(), "DEBUG")
return False
finally:
# 清理资源
self.log("清理资源...")
if self.ssh_client:
try:
self.ssh_client.close()
except:
pass
if self.ssh_shell:
try:
self.ssh_shell.close()
except:
pass
self.close_browser()
def main():
"""主函数"""
# 配置参数
config = {
'host': '192.168.5.52',
'username': 'root',
'password': 'Ubains@123',
'license_path': r'E:\自动化部署\X86-5.52\license.zip'
}
# 创建部署实例并执行
deployment = RemoteDeploymentAutomation(**config)
# 执行完整部署
success = deployment.run_full_deployment()
# 返回结果
sys.exit(0 if success else 1)
if __name__ == '__main__':
main()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
自动处理whiptail菜单的部署脚本
使用paramiko的invoke_shell和自动响应
"""
import sys
import os
import time
import threading
import queue
# 添加当前目录到路径
sys.path.insert(0, os.path.dirname(__file__))
import paramiko
class DeploymentAutomation:
def __init__(self, host, username, password):
self.host = host
self.username = username
self.password = password
self.client = None
self.shell = None
self.output_queue = queue.Queue()
def log(self, message, level="INFO"):
"""日志输出"""
prefix = {"INFO": "[OK]", "ERROR": "[ERROR]", "WARN": "[WARN]"}
print(f"{prefix.get(level, '[INFO]')} {message}")
def connect(self):
"""连接SSH"""
try:
self.client = paramiko.SSHClient()
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.client.connect(self.host, username=self.username, password=self.password, timeout=30)
self.log("SSH连接成功")
return True
except Exception as e:
self.log(f"SSH连接失败: {str(e)}", "ERROR")
return False
def create_shell(self):
"""创建交互式shell"""
try:
self.shell = self.client.invoke_shell()
time.sleep(1)
self.log("交互式shell创建成功")
return True
except Exception as e:
self.log(f"Shell创建失败: {str(e)}", "ERROR")
return False
def read_output(self, timeout=5):
"""读取shell输出"""
try:
output = ""
start_time = time.time()
while time.time() - start_time < timeout:
if self.shell.recv_ready():
chunk = self.shell.recv(4096).decode('utf-8', errors='ignore')
output += chunk
if chunk:
start_time = time.time() # 重置超时
else:
time.sleep(0.1)
return output
except:
return ""
def send_command(self, command, wait_time=1):
"""发送命令"""
try:
self.shell.send(command + "\n")
time.sleep(wait_time)
except Exception as e:
self.log(f"发送命令失败: {str(e)}", "ERROR")
def run_deployment(self):
"""执行部署"""
try:
self.log("开始部署流程")
# 清空初始缓冲区
self.read_output(timeout=1)
# 切换到部署目录
self.log("切换到部署目录")
self.send_command("cd /data/offline_auto_unifiedPlatform", wait_time=2)
# 运行部署脚本
self.log("启动部署脚本 (new_auto.sh)")
self.send_command("./new_auto.sh", wait_time=3)
# 监控部署过程
self.log("监控部署过程,等待菜单出现...")
deployment_start = time.time()
max_time = 2400 # 40分钟
menu_handled = False
while time.time() - deployment_start < max_time:
# 读取输出
output = self.read_output(timeout=10)
if output:
# 检测whiptail菜单
if 'whiptail' in output or '选择系统' in output:
if not menu_handled:
self.log("检测到whiptail菜单,自动选择'全部系统'")
# 按空格键选中,然后按回车确认
self.shell.send(" ")
time.sleep(1)
self.shell.send("\n")
time.sleep(2)
menu_handled = True
# 检测其他提示
elif 'Press any key' in output or '按任意键' in output:
self.log("检测到按键提示,发送回车")
self.send_command("", wait_time=1)
# 检测部署完成
elif '部署完成' in output or '部署成功' in output:
self.log("部署完成!")
break
# 检测错误
elif 'error' in output.lower() and 'fatal' in output.lower():
self.log(f"检测到错误: {output[-200:]}", "WARN")
# 每60秒输出进度
elapsed = int(time.time() - deployment_start)
if elapsed % 60 == 0 and elapsed > 0:
self.log(f"部署进行中... 已用时: {int(elapsed/60)}分钟")
# 检查部署结果
self.log("检查部署结果")
self.send_command("docker ps --format 'table {{.Names}}\t{{.Status}}'", wait_time=3)
docker_output = self.read_output(timeout=5)
print("\n" + "=" * 50)
print("部署完成 - 容器状态:")
print("=" * 50)
print(docker_output)
container_count = docker_output.count('\n') - 1
print(f"\n运行中的容器数量: {container_count}")
if container_count >= 5:
self.log("部署成功完成!")
return True
else:
self.log("部署可能未完全完成", "WARN")
return False
except Exception as e:
self.log(f"部署过程出错: {str(e)}", "ERROR")
import traceback
traceback.print_exc()
return False
def close(self):
"""关闭连接"""
if self.shell:
self.shell.close()
if self.client:
self.client.close()
def main():
print("=" * 60)
print("自动化部署脚本 (带whiptail菜单自动处理)")
print("=" * 60)
deployment = DeploymentAutomation(
host='192.168.5.52',
username='root',
password='Ubains@123'
)
try:
if not deployment.connect():
return 1
if not deployment.create_shell():
return 1
success = deployment.run_deployment()
print("\n" + "=" * 60)
if success:
print("部署执行完成")
print("\n后续步骤:")
print("1. 系统授权: https://192.168.5.52/#/LoginConfig")
print(" 账号: superadmin / Ubains@1357")
print(" 验证码: csba")
print("\n2. 创建管理员: 为'自动化'公司创建admin用户")
else:
print("部署未完全完成,请检查日志")
print("=" * 60)
return 0 if success else 1
finally:
deployment.close()
if __name__ == '__main__':
sys.exit(main())
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$PlinkPath = Join-Path $ScriptDir "plink.exe"
function Invoke-SSH {
param([string]$Command)
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw Ubains@123 -P 22 root@192.168.5.52 $Command"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit(60000)
return $p.StandardOutput.ReadToEnd()
}
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Checking /data directory on server" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
$result = Invoke-SSH -Command "ls -la /data"
Write-Host $result
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Looking for deployment scripts" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
$scripts = Invoke-SSH -Command "find /data -name '*.sh' -type f 2>/dev/null | head -20"
Write-Host $scripts
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Checking Docker status" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
$docker = Invoke-SSH -Command "docker ps -a 2>&1"
Write-Host $docker
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$PlinkPath = Join-Path $ScriptDir "plink.exe"
$ServerIP = "192.168.5.52"
$Username = "root"
$Password = "Ubains@123"
$SSHPort = 22
Write-Host "Checking deployment packages on server..." -ForegroundColor Cyan
Write-Host ""
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw $Password -P $SSHPort ${Username}@${ServerIP} 'ls -la /data && echo --- && find /data -maxdepth 2 -name *.sh -type f 2>/dev/null'"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit(60000)
$stdout = $p.StandardOutput.ReadToEnd()
Write-Host $stdout
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$PlinkPath = Join-Path $ScriptDir "plink.exe"
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw Ubains@123 -P 22 root@192.168.5.52 'ls -la /home && echo --- && ls -la /home/deploy 2>&1'"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit(30000)
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
Write-Host $stdout
Write-Host $stderr
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
受控部署脚本 - 分步骤执行部署
"""
import sys
import os
import time
# 添加当前目录到路径
sys.path.insert(0, os.path.dirname(__file__))
from auto_deployment_python import RemoteDeploymentAutomation
def main():
print("=" * 50)
print("受控自动化部署")
print("=" * 50)
config = {
'host': '192.168.5.52',
'username': 'root',
'password': 'Ubains@123',
'license_path': r'E:\自动化部署\X86-5.52\license.zip'
}
deployment = RemoteDeploymentAutomation(**config)
try:
# 步骤1: 连接SSH并准备环境
print("\n步骤1: 连接SSH并准备环境")
print("-" * 50)
if not deployment.connect_ssh():
print("[ERROR] SSH连接失败")
return 1
print("[OK] SSH连接成功")
if not deployment.prepare_deployment_environment():
print("[ERROR] 环境准备失败")
return 1
print("[OK] 环境准备完成")
# 步骤2: 启动部署脚本
print("\n步骤2: 启动部署脚本")
print("-" * 50)
print("注意: 此步骤需要手动选择'全部系统'选项")
print("部署预计需要40分钟时间...")
# 创建交互式会话
if not deployment.connect_ssh_interactive():
print("[ERROR] 交互式连接失败")
return 1
# 切换到部署目录
print("切换到部署目录...")
deployment.ssh_shell.send("cd /data/offline_auto_unifiedPlatform\n")
time.sleep(2)
# 清空缓冲区
try:
while deployment.ssh_shell.recv_ready():
deployment.ssh_shell.recv(1024)
except:
pass
# 启动部署脚本
print("启动部署脚本 (new_auto.sh)...")
deployment.ssh_shell.send("./new_auto.sh\n")
time.sleep(3)
# 监控部署过程
print("开始监控部署过程...")
print("如果出现菜单,请手动选择'全部系统'选项")
deployment_start = time.time()
max_deployment_time = 2400 # 40分钟
menu_detected = False
output_buffer = ""
while time.time() - deployment_start < max_deployment_time:
try:
if deployment.ssh_shell.recv_ready():
chunk = deployment.ssh_shell.recv(4096).decode('utf-8', errors='ignore')
output_buffer += chunk
# 检测菜单
if 'whiptail' in chunk or '选择系统' in chunk or '全部系统' in chunk:
if not menu_detected:
print("\n[检测到菜单] 尝试自动选择'全部系统'...")
deployment.ssh_shell.send("\n")
menu_detected = True
time.sleep(2)
# 检测部署开始
if '开始部署' in output_buffer or '正在部署' in output_buffer:
if not menu_detected:
print("\n[OK] 部署已开始")
menu_detected = True
# 检测部署完成
if '部署完成' in output_buffer or '部署成功' in output_buffer:
print("\n[OK] 部署完成!")
break
# 检测错误
if 'error' in chunk.lower() and 'fatal' in chunk.lower():
print(f"\n[ERROR] 检测到严重错误")
print(f"错误信息: {chunk[-200:]}")
# 每60秒输出进度
elapsed = int(time.time() - deployment_start)
if elapsed % 60 == 0 and elapsed > 0:
print(f"[进度] 部署进行中... 已用时: {int(elapsed/60)}分钟")
time.sleep(5)
except Exception as e:
print(f"[WARN] 监控时出错: {str(e)}")
time.sleep(5)
# 步骤3: 检查部署结果
print("\n步骤3: 检查部署结果")
print("-" * 50)
deployment.ssh_shell.send("docker ps --format 'table {{.Names}}\t{{.Status}}'\n")
time.sleep(3)
docker_output = ""
try:
while deployment.ssh_shell.recv_ready():
docker_output += deployment.ssh_shell.recv(4096).decode('utf-8', errors='ignore')
except:
pass
print("容器状态:")
print(docker_output)
# 统计容器数量
container_count = docker_output.count('\n') - 1 # 减去表头
print(f"\n运行中的容器数量: {container_count}")
if container_count >= 5:
print("[OK] 部署成功,已启动多个容器")
elif container_count > 0:
print("[WARN] 部署可能未完全完成,容器数量较少")
else:
print("[ERROR] 部署可能失败,没有容器运行")
# 清理
print("\n清理连接...")
deployment.ssh_client.close()
if deployment.ssh_shell:
deployment.ssh_shell.close()
print("\n" + "=" * 50)
print("部署脚本执行完成")
print("=" * 50)
print("\n后续步骤:")
print("1. 系统授权: https://192.168.5.52/#/LoginConfig")
print(" 账号: superadmin / Ubains@1357")
print(" 验证码: csba")
print(" 授权文件: E:\\自动化部署\\X86-5.52\\license.zip")
print("\n2. 创建管理员: 为'自动化'公司创建admin用户")
print("\n3. 验收测试: 检查服务接口状态")
return 0
except Exception as e:
print(f"\n[ERROR] 部署过程出错: {str(e)}")
import traceback
traceback.print_exc()
return 1
if __name__ == '__main__':
sys.exit(main())
#!/usr/bin/expect -f
# 自动处理部署脚本的交互式提示
set timeout 300
# 设置服务器连接信息
set host "192.168.5.52"
set username "root"
set password "Ubains@123"
# 连接到SSH服务器
spawn ssh $username@$host
expect {
"yes/no" {
send "yes\r"
exp_continue
}
"password:" {
send "$password\r"
}
timeout {
puts "连接超时"
exit 1
}
}
# 等待shell提示符
expect "~]#"
# 切换到部署目录
send "cd /data/offline_auto_unifiedPlatform\r"
expect "~]#"
# 运行部署脚本
send "./new_auto.sh\r"
# 处理各种交互式提示
expect {
# "是否继续执行脚本(y/n)" 提示
"是否继续执行脚本" {
send "y\r"
exp_continue
}
# "确认当前机器信息" 提示
"确认当前机器信息" {
send "y\r"
exp_continue
}
# "确认无误请按" 提示
"确认无误请按" {
send "\r"
exp_continue
}
# "请输入当前日期" 提示
"请输入当前日期" {
# 获取当前日期
set current_date [clock format [clock seconds] -format "%Y/%m/%d"]
send "$current_date\r"
exp_continue
}
# "请输入当前时间" 提示
"请输入当前时间" {
# 获取当前时间
set current_time [clock format [clock seconds] -format "%H:%M:%S"]
send "$current_time\r"
exp_continue
}
# "是否使用自定义NTP" 提示
"是否使用自定义NTP" {
send "n\r"
exp_continue
}
# whiptail系统选择菜单
"whiptail" {
# 发送空格选择"全部系统",然后回车确认
send " "
sleep 1
send "\r"
exp_continue
}
# "选择系统" 提示
"选择系统" {
send "\r"
exp_continue
}
# 部署完成
"部署完成" {
puts "部署完成!"
send "\r"
}
# 部署成功
"部署成功" {
puts "部署成功!"
send "\r"
}
# 超时处理(长时间等待)
timeout {
# 检查是否部署还在进行
puts "等待部署中..."
exp_continue
}
# EOF处理
eof {
puts "脚本执行结束"
}
}
# 等待一段时间以查看输出
expect "~]#" {
puts "返回到shell提示符"
}
# 检查容器状态
send "docker ps --format 'table {{.Names}}\t{{.Status}}'\r"
expect "~]#"
# 保持连接打开以便查看输出
interact
# Deployment Check Script - Simplified Version
# Author: Automation Team
# Date: 2026-05-14
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$ReportsDir = Join-Path $ScriptDir "reports"
if (-not (Test-Path $ReportsDir)) {
New-Item -ItemType Directory -Path $ReportsDir -Force | Out-Null
}
$LogFile = Join-Path $ReportsDir "deploy_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
function Write-Log {
param([string]$Message, [string]$Color = "White")
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogMessage = "[$Timestamp] $Message"
Write-Host $LogMessage -ForegroundColor $Color
Add-Content -Path $LogFile -Value $LogMessage
}
function Invoke-SSHCommand {
param([string]$Command)
$PlinkPath = Join-Path $ScriptDir "plink.exe"
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw $Password -P $SSHPort ${Username}@${ServerIP} $Command"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit(60000)
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
return @{
Output = $stdout
ExitCode = $p.ExitCode
}
}
# Configuration
$ServerIP = "192.168.5.52"
$Username = "root"
$Password = "Ubains@123"
$SSHPort = 22
$Results = @{}
Write-Log "========================================" "Cyan"
Write-Log "Deployment Check Script" "Cyan"
Write-Log "Target: ${ServerIP}" "Cyan"
Write-Log "========================================" "Cyan"
# Test connection
Write-Log "Testing SSH connection..." "Yellow"
$result = Invoke-SSHCommand -Command "echo 'ok'"
if ($result.Output -match "ok") {
Write-Log "Connection successful" "Green"
$Results.Connection = "OK"
} else {
Write-Log "Connection failed" "Red"
exit 1
}
# Get server info
Write-Log "Getting server information..." "Yellow"
$osInfo = Invoke-SSHCommand -Command "uname -a"
Write-Log "OS: $($osInfo.Output.Trim())" "White"
$diskInfo = Invoke-SSHCommand -Command "df -h /home | awk 'NR==2 {print \$4}'"
Write-Log "Disk space: $($diskInfo.Output.Trim())" "White"
# Check Docker
Write-Log "Checking Docker status..." "Yellow"
$dockerResult = Invoke-SSHCommand -Command "docker ps --format 'table {{.Names}}\t{{.Status}}' 2>&1"
if ($dockerResult.ExitCode -eq 0) {
Write-Log "Docker is running" "Green"
Write-Host ""
Write-Host "========== Containers ==========" -ForegroundColor Cyan
Write-Host $dockerResult.Output
Write-Host "========== Containers End ==========" -ForegroundColor Cyan
Write-Host ""
$Results.Docker = "Running"
} else {
Write-Log "Docker is not accessible" "Red"
$Results.Docker = "Not Running"
}
# Check services
Write-Log "Checking services..." "Yellow"
$services = @(
@{Name="ExtAPI"; Path="/data/services/api/java-meeting/java-meeting-extapi/logs/ubains-INFO-AND-ERROR.log"},
@{Name="InnerAPI"; Path="/data/services/api/java-meeting/java-meeting2.0/logs/ubains-INFO-AND-ERROR.log"},
@{Name="Monitor"; Path="/data/services/api/python-cmdb/log/uinfo.log"},
@{Name="Voice"; Path="/data/services/api/python-voice/log/uinfo.log"}
)
foreach ($svc in $services) {
$logResult = Invoke-SSHCommand -Command "test -f '$($svc.Path)' && echo 'exists' || echo 'not_found'"
if ($logResult.Output -match "exists") {
$tailResult = Invoke-SSHCommand -Command "tail -20 '$($svc.Path)'"
if ($tailResult.Output -match "ERROR|Exception") {
Write-Log "$($svc.Name): Log contains errors" "Yellow"
$Results[$svc.Name] = "Has Errors"
} else {
Write-Log "$($svc.Name): Log OK" "Green"
$Results[$svc.Name] = "OK"
}
} else {
Write-Log "$($svc.Name): Log file not found" "Red"
$Results[$svc.Name] = "Not Found"
}
}
# Test APIs
Write-Log "Testing API endpoints..." "Yellow"
$apis = @(
@{Name="ExtAPI"; URL="https://${ServerIP}/exapi/message/getMsgPageList"; Expected="A0076"},
@{Name="Meeting"; URL="https://${ServerIP}/meetingV3/api/systemConfiguration/globalConfig?companyNumber=CN-SZ-00-0201"; Expected="A0078"},
@{Name="Monitor"; URL="https://${ServerIP}/monitor/api2/api/servermonitor/"; Expected="40000014"},
@{Name="Voice"; URL="https://${ServerIP}/voice/api/iflytek/roommaster?company_id=1&user_id=8&company_secret=57d00f9f-020f-5f1f-b788-55fae843bceb&getall=1"; Expected="40000003"}
)
foreach ($api in $apis) {
$curlResult = Invoke-SSHCommand -Command "curl -k '$($api.URL)' 2>/dev/null"
if ($curlResult.Output -match $api.Expected) {
Write-Log "$($api.Name): API OK" "Green"
$Results["$($api.Name)API"] = "OK"
} else {
Write-Log "$($api.Name): API Error" "Yellow"
$Results["$($api.Name)API"] = "Error"
}
}
# Generate report
Write-Log "Generating report..." "Yellow"
$report = @"
# Deployment Check Report
## Server: $ServerIP
## Results
- Connection: $($Results.Connection)
- Docker: $($Results.Docker)
## Services
"@
foreach ($svc in $services) {
$report += "`n- $($svc.Name): $($Results[$svc.Name])"
}
$report += "`n\n## APIs`n"
foreach ($api in $apis) {
$report += "`n- $($api.Name): $($Results["$($api.Name)API"])"
}
$report += @"
## Access URLs
- Frontend: https://${ServerIP}/
- Maintenance: https://${ServerIP}/#/LoginConfig
- Backend: https://${ServerIP}/#/LoginAdmin
---
Generated: $(Get-Date)
"@
$reportFile = Join-Path $ReportsDir "${ServerIP}_check_$(Get-Date -Format 'yyyyMMdd_HHmmss').md"
$report | Out-File -FilePath $reportFile -Encoding UTF8 -Force
Write-Log "Report saved to: $reportFile" "Green"
Write-Log "========================================" "Green"
Write-Log "Check completed!" "Green"
Write-Log "========================================" "Green"
#!/bin/bash
# 自动响应部署脚本的交互式提示
cd /data/offline_auto_unifiedPlatform
# 使用输入重定向自动响应所有提示
./new_auto.sh <<EOF
1
y
y
y
y
y
EOF
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$PlinkPath = Join-Path $ScriptDir "plink.exe"
function Invoke-SSH {
param([string]$Command, [int]$TimeoutMs = 600000)
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw Ubains@123 -P 22 root@192.168.5.52 $Command"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit($TimeoutMs)
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
return @{
Output = $stdout
Error = $stderr
ExitCode = $p.ExitCode
}
}
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Executing Deployment Script" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# First, let's check the deployment script help
Write-Host "Step 1: Checking deployment script information..." -ForegroundColor Yellow
$helpResult = Invoke-SSH -Command "cd /data/offline_auto_unifiedPlatform && head -50 new_auto.sh"
Write-Host "Deployment script header:" -ForegroundColor Gray
Write-Host ($helpResult.Output | Select-Object -First 30)
Write-Host ""
# Check script permissions and make executable
Write-Host "Step 2: Setting script permissions..." -ForegroundColor Yellow
$chmodResult = Invoke-SSH -Command "chmod +x /data/offline_auto_unifiedPlatform/*.sh"
Write-Host "Permissions set" -ForegroundColor Green
Write-Host ""
# Start the deployment script in background with logging
Write-Host "Step 3: Starting deployment script..." -ForegroundColor Yellow
Write-Host "This will take approximately 40 minutes..." -ForegroundColor Gray
Write-Host ""
# Create log directory
$mkdirResult = Invoke-SSH -Command "mkdir -p /var/log/deploy"
# Run deployment in background with output logging
$deployCmd = "cd /data/offline_auto_unifiedPlatform && nohup bash new_auto.sh > /var/log/deploy/deploy.log 2>&1 & echo $!"
$pidResult = Invoke-SSH -Command $deployCmd
$deployPid = $pidResult.Output.Trim()
Write-Host "Deployment started with PID: $deployPid" -ForegroundColor Green
Write-Host "Log file: /var/log/deploy/deploy.log" -ForegroundColor Gray
Write-Host ""
# Monitor initial output
Write-Host "Waiting for deployment to initialize..." -ForegroundColor Yellow
Start-Sleep -Seconds 10
# Check if process is still running
$checkResult = Invoke-SSH -Command "ps aux | grep $deployPid | grep -v grep"
if ($checkResult.Output) {
Write-Host "Deployment process is running!" -ForegroundColor Green
Write-Host ""
# Show initial log output
$logResult = Invoke-SSH -Command "tail -50 /var/log/deploy/deploy.log 2>/dev/null || echo 'Log not available yet'"
if ($logResult.Output -ne "Log not available yet") {
Write-Host "Initial deployment output:" -ForegroundColor Gray
Write-Host $logResult.Output
}
} else {
Write-Host "Deployment process may have completed quickly or exited" -ForegroundColor Yellow
Write-Host ""
# Check exit status
$logResult = Invoke-SSH -Command "cat /var/log/deploy/deploy.log 2>/dev/null || echo 'No log file'"
Write-Host "Deployment log:" -ForegroundColor Gray
Write-Host $logResult.Output
}
Write-Host ""
Write-Host "========================================" -ForegroundColor Green
Write-Host "Deployment is running in background!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host ""
Write-Host "To monitor deployment progress, SSH into server and run:" -ForegroundColor Yellow
Write-Host " tail -f /var/log/deploy/deploy.log" -ForegroundColor Gray
Write-Host ""
Write-Host "To check if deployment is still running:" -ForegroundColor Yellow
Write-Host " ps aux | grep new_auto.sh" -ForegroundColor Gray
Write-Host ""
# Setup monitoring loop
Write-Host "Press Ctrl+C to stop monitoring" -ForegroundColor Yellow
Write-Host "Monitoring deployment progress (will show last 20 lines every 30 seconds)..." -ForegroundColor Gray
Write-Host ""
$maxWait = 3600 # 60 minutes max
$elapsed = 0
$lastLines = ""
while ($elapsed -lt $maxWait) {
Start-Sleep -Seconds 30
$elapsed += 30
$minutes = [math]::Floor($elapsed / 60)
# Get latest log lines
$logResult = Invoke-SSH -Command "tail -20 /var/log/deploy/deploy.log 2>/dev/null"
if ($logResult.Output -and $logResult.Output -ne $lastLines) {
$lastLines = $logResult.Output
Write-Host "========================================" -ForegroundColor DarkGray
Write-Host "Progress update ($minutes minutes):" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor DarkGray
Write-Host $lastLines
Write-Host ""
}
# Check if process still running
$checkResult = Invoke-SSH -Command "ps aux | grep new_auto.sh | grep -v grep | wc -l"
if ($checkResult.Output.Trim() -eq "0") {
Write-Host "Deployment process has completed!" -ForegroundColor Green
Write-Host ""
# Show final log
$finalLog = Invoke-SSH -Command "tail -100 /var/log/deploy/deploy.log"
Write-Host "Final deployment log:" -ForegroundColor Gray
Write-Host $finalLog.Output
break
}
}
Write-Host ""
Write-Host "========================================" -ForegroundColor Green
Write-Host "Deployment monitoring completed!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host ""
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$PlinkPath = Join-Path $ScriptDir "plink.exe"
function Invoke-SSH {
param([string]$Command, [int]$TimeoutMs = 600000)
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw Ubains@123 -P 22 root@192.168.5.52 $Command"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit($TimeoutMs)
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
return @{
Output = $stdout
Error = $stderr
ExitCode = $p.ExitCode
}
}
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Deployment Package Extraction & Deploy" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# Step 1: Verify MD5 checksum
Write-Host "Step 1: Verifying MD5 checksum..." -ForegroundColor Yellow
$md5Result = Invoke-SSH -Command "cd /data && md5sum -c offline_auto_unifiedPlatform.tar.gz.md5"
if ($md5Result.Output -match "OK") {
Write-Host "MD5 checksum verified: OK" -ForegroundColor Green
} else {
Write-Host "MD5 checksum check:" -ForegroundColor Yellow
Write-Host $md5Result.Output
Write-Host "Warning: MD5 check failed, but continuing..." -ForegroundColor Yellow
}
Write-Host ""
# Step 2: Extract deployment package
Write-Host "Step 2: Extracting deployment package..." -ForegroundColor Yellow
Write-Host "This may take 10-30 minutes depending on file size..." -ForegroundColor Gray
Write-Host ""
# Extract in background with nohup
$extractCmd = "cd /data && nohup tar -xzf offline_auto_unifiedPlatform.tar.gz > /tmp/extract.log 2>&1 & echo $!"
$pidResult = Invoke-SSH -Command $extractCmd
Write-Host "Extraction process started with PID: $($pidResult.Output.Trim())" -ForegroundColor Green
Write-Host "You can monitor progress with: tail -f /tmp/extract.log" -ForegroundColor Gray
Write-Host ""
# Wait a bit and check if extraction is happening
Start-Sleep -Seconds 10
$checkResult = Invoke-SSH -Command "ps aux | grep tar | grep -v grep"
if ($checkResult.Output) {
Write-Host "Extraction is in progress..." -ForegroundColor Green
Write-Host $checkResult.Output
Write-Host ""
} else {
# Check if extraction completed quickly
$lsResult = Invoke-SSH -Command "ls -la /data | grep -E '^d'"
Write-Host "Current directories in /data:" -ForegroundColor Gray
Write-Host $lsResult.Output
Write-Host ""
}
# Step 3: Check for deployment scripts after extraction
Write-Host "Step 3: Looking for deployment scripts..." -ForegroundColor Yellow
Write-Host "Waiting for extraction to complete..." -ForegroundColor Gray
Write-Host ""
# Wait for extraction (check every 30 seconds)
$maxWait = 1800 # 30 minutes max
$elapsed = 0
while ($elapsed -lt $maxWait) {
$checkExtract = Invoke-SSH -Command "test -f /tmp/extract.log && tail -5 /tmp/extract.log || echo 'no log'"
if ($checkExtract.Output -notmatch "no log") {
Write-Host "Extract log: $($checkExtract.Output.Trim())" -ForegroundColor Gray
}
# Check if tar process is still running
$tarRunning = Invoke-SSH -Command "ps aux | grep 'tar.*offline_auto' | grep -v grep | wc -l"
if ($tarRunning.Output.Trim() -eq "0") {
Write-Host "Extraction completed!" -ForegroundColor Green
break
}
Start-Sleep -Seconds 30
$elapsed += 30
$minutes = [math]::Floor($elapsed / 60)
Write-Host "Still extracting... ($minutes minutes elapsed)" -ForegroundColor Yellow
}
Write-Host ""
# Final check of extracted contents
Write-Host "Step 4: Checking extracted contents..." -ForegroundColor Yellow
$lsResult = Invoke-SSH -Command "ls -la /data"
Write-Host "Contents of /data:" -ForegroundColor Gray
Write-Host $lsResult.Output
Write-Host ""
# Find deployment scripts
$scriptsResult = Invoke-SSH -Command "find /data -maxdepth 3 -name '*.sh' -type f 2>/dev/null | head -20"
if ($scriptsResult.Output) {
Write-Host "Found deployment scripts:" -ForegroundColor Green
$scriptsResult.Output -split "`n" | Where-Object { $_ -ne "" } | ForEach-Object {
Write-Host " $_" -ForegroundColor Gray
}
} else {
Write-Host "No deployment scripts found yet" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "========================================" -ForegroundColor Green
Write-Host "Extraction completed!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host ""
Write-Host "Next steps:" -ForegroundColor Yellow
Write-Host "1. Check the extracted deployment scripts above" -ForegroundColor Gray
Write-Host "2. Run the main deployment script" -ForegroundColor Gray
Write-Host "3. Monitor deployment progress" -ForegroundColor Gray
Write-Host ""
# Complete Remote Deployment Script - New Unified Platform
# Author: Automation Team
# Date: 2026-05-14
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$ReportsDir = Join-Path $ScriptDir "reports"
$TempDir = Join-Path $ScriptDir "temp"
# Create directories
if (-not (Test-Path $ReportsDir)) { New-Item -ItemType Directory -Path $ReportsDir -Force | Out-Null }
if (-not (Test-Path $TempDir)) { New-Item -ItemType Directory -Path $TempDir -Force | Out-Null }
$LogFile = Join-Path $ReportsDir "deploy_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
function Write-Log {
param([string]$Message, [string]$Level = "INFO")
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogMessage = "[$Timestamp] [$Level] $Message"
$Color = switch($Level) {
"INFO" { "White" }
"OK" { "Green" }
"WARN" { "Yellow" }
"ERROR" { "Red" }
"STEP" { "Cyan" }
default { "White" }
}
Write-Host $LogMessage -ForegroundColor $Color
Add-Content -Path $LogFile -Value $LogMessage
}
function Invoke-SSHCommand {
param([string]$Command, [int]$TimeoutMs = 300000)
$PlinkPath = Join-Path $ScriptDir "plink.exe"
$StartInfo = New-Object System.Diagnostics.ProcessStartInfo
$StartInfo.FileName = $PlinkPath
$StartInfo.Arguments = "-pw $Password -P $SSHPort ${Username}@${ServerIP} $Command"
$StartInfo.UseShellExecute = $false
$StartInfo.RedirectStandardOutput = $true
$StartInfo.RedirectStandardError = $true
$StartInfo.CreateNoWindow = $true
$Process = New-Object System.Diagnostics.Process
$Process.StartInfo = $StartInfo
try {
$Process.Start() | Out-Null
$Process.WaitForExit($TimeoutMs)
$Output = $Process.StandardOutput.ReadToEnd()
$StdErr = $Process.StandardError.ReadToEnd()
return @{
Success = ($Process.ExitCode -eq 0)
Output = $Output
Error = $StdErr
ExitCode = $Process.ExitCode
}
}
catch {
return @{
Success = $false
Output = ""
Error = $_.Exception.Message
ExitCode = -1
}
}
}
# Configuration
$ServerIP = "192.168.5.52"
$Username = "root"
$Password = "Ubains@123"
$SSHPort = 22
$DeployResults = @{
Connection = ""
ServerInfo = @{}
ContainerStatus = @{}
ServiceLogs = @{}
APITests = @{}
}
# Start deployment
Write-Log "========================================" "STEP"
Write-Log "New Unified Platform Deployment Script" "STEP"
Write-Log "Target: ${ServerIP} (X86)" "STEP"
Write-Log "Start: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" "STEP"
Write-Log "========================================" "STEP"
# Step 1: Test SSH connection
Write-Log "Step 1: Testing SSH connection" "STEP"
$TestResult = Invoke-SSHCommand -Command "echo 'connection_ok'"
if ($TestResult.Output -match "connection_ok") {
Write-Log "SSH connection successful" "OK"
$DeployResults.Connection = "成功"
} else {
Write-Log "SSH connection failed: $($TestResult.Error)" "ERROR"
exit 1
}
# Step 2: Get server information
Write-Log "`nStep 2: Getting server information" "STEP"
$OSInfo = Invoke-SSHCommand -Command "uname -a"
$DeployResults.ServerInfo.OS = $OSInfo.Output.Trim()
Write-Log "OS: $($DeployResults.ServerInfo.OS)" "INFO"
$DiskInfo = Invoke-SSHCommand -Command "df -h /home | awk 'NR==2 {print \$4}'"
$DeployResults.ServerInfo.DiskSpace = $DiskInfo.Output.Trim()
Write-Log "Home disk space: $($DeployResults.ServerInfo.DiskSpace)" "INFO"
# Check platform type
$PlatformCheck = Invoke-SSHCommand -Command "test -d /data/services && echo 'new' || echo 'old'"
$DeployResults.ServerInfo.PlatformType = $PlatformCheck.Output.Trim()
Write-Log "Platform type: $($DeployResults.ServerInfo.PlatformType)" "INFO"
# Step 3: Check Docker status
Write-Log "`nStep 3: Checking Docker status" "STEP"
$DockerCheck = Invoke-SSHCommand -Command "docker ps --format 'table {{.Names}}\t{{.Status}}' 2>&1"
if ($DockerCheck.ExitCode -eq 0) {
Write-Log "Docker is running" "OK"
Write-Host "`n========== Container Status ==========" -ForegroundColor Cyan
Write-Host $DockerCheck.Output
Write-Host "========== Container Status End ==========`n" -ForegroundColor Cyan
# Parse container status
$Lines = $DockerCheck.Output -split "`n"
foreach ($Line in $Lines) {
if ($Line -match "(\S+)\s+(\S+)") {
$Name = $Matches[1]
$Status = $Matches[2]
if ($Name -ne "NAMES") {
$DeployResults.ContainerStatus[$Name] = $Status
}
}
}
} else {
Write-Log "Docker is not running or not accessible" "WARN"
$DeployResults.ContainerStatus.Error = "Docker不可用"
}
# Step 4: Check service logs
Write-Log "`nStep 4: Checking service logs" "STEP"
$LogPaths = @{
"ExtAPI" = "/data/services/api/java-meeting/java-meeting-extapi/logs/ubains-INFO-AND-ERROR.log"
"InnerAPI" = "/data/services/api/java-meeting/java-meeting2.0/logs/ubains-INFO-AND-ERROR.log"
"Monitor" = "/data/services/api/python-cmdb/log/uinfo.log"
"Voice" = "/data/services/api/python-voice/log/uinfo.log"
}
foreach ($LogName in $LogPaths.Keys) {
$LogPath = $LogPaths[$LogName]
Write-Log "Checking $LogName log..." "INFO"
$LogResult = Invoke-SSHCommand -Command "tail -50 '$LogPath' 2>/dev/null || echo 'not_found'"
if ($LogResult.Output -match "not_found") {
Write-Log "$LogName log file not found" "WARN"
$DeployResults.ServiceLogs[$LogName] = "文件不存在"
} elseif ($LogName -eq "ExtAPI" -and $LogResult.Output -match "SYSTEMVERSION") {
Write-Log "$LogName log is normal (version detected)" "OK"
$DeployResults.ServiceLogs[$LogName] = "正常"
} elseif ($LogResult.Output -match "ERROR|Exception|Failed") {
Write-Log "$LogName log contains errors" "WARN"
$DeployResults.ServiceLogs[$LogName] = "发现异常"
} else {
Write-Log "$LogName log appears normal" "OK"
$DeployResults.ServiceLogs[$LogName] = "正常"
}
}
# Step 5: Test API endpoints
Write-Log "`nStep 5: Testing service endpoints" "STEP"
$APITests = @{
"ExtAPI" = @{ URL = "https://${ServerIP}/exapi/message/getMsgPageList"; Expected = "A0076" }
"Meeting" = @{ URL = "https://${ServerIP}/meetingV3/api/systemConfiguration/globalConfig?companyNumber=CN-SZ-00-0201"; Expected = "A0078" }
"Monitor" = @{ URL = "https://${ServerIP}/monitor/api2/api/servermonitor/"; Expected = "40000014" }
"Voice" = @{ URL = "https://${ServerIP}/voice/api/iflytek/roommaster?company_id=1&user_id=8&company_secret=57d00f9f-020f-5f1f-b788-55fae843bceb&getall=1"; Expected = "40000003" }
}
foreach ($APIName in $APITests.Keys) {
$API = $APITests[$APIName]
Write-Log "Testing $APIName endpoint..." "INFO"
$CurlResult = Invoke-SSHCommand -Command "curl -k '$($API.URL)' 2>/dev/null" -TimeoutMs 60000
if ($CurlResult.Output -match $API.Expected) {
Write-Log "$APIName endpoint is normal" "OK"
$DeployResults.APITests[$APIName] = "正常"
} elseif ($CurlResult.Output -match "nginx|Error") {
Write-Log "$APIName endpoint returns error page" "WARN"
$DeployResults.APITests[$APIName] = "异常"
} else {
Write-Log "$APIName endpoint: unknown response" "WARN"
$DeployResults.APITests[$APIName] = "未知"
}
}
# Step 6: Generate report
Write-Log "`nStep 6: Generating deployment report" "STEP"
$ReportContent = @"
# New Unified Platform Deployment Report
## Basic Information
- Server IP: $ServerIP
- Architecture: X86
- Deployment Time: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
## Deployment Results
### 1. SSH Connection
- Status: $($DeployResults.Connection)
### 2. Server Information
- OS: $($DeployResults.ServerInfo.OS)
- Disk Space: $($DeployResults.ServerInfo.DiskSpace)
- Platform: $($DeployResults.ServerInfo.PlatformType)
### 3. Container Status
"@
foreach ($Container in $DeployResults.ContainerStatus.Keys) {
$ReportContent += "`n- $Container : $($DeployResults.ContainerStatus[$Container])"
}
$ReportContent += @"
### 4. Service Logs
"@
foreach ($Log in $DeployResults.ServiceLogs.Keys) {
$ReportContent += "`n- $Log : $($DeployResults.ServiceLogs[$Log])"
}
$ReportContent += @"
### 5. API Tests
"@
foreach ($API in $DeployResults.APITests.Keys) {
$ReportContent += "`n- $API : $($DeployResults.APITests[$API])"
}
$ReportContent += @"
## System Access Addresses
- Frontend: https://${ServerIP}/
- Maintenance: https://${ServerIP}/#/LoginConfig
- Backend: https://${ServerIP}/#/LoginAdmin
---
Report Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
"@
$ReportFile = Join-Path $ReportsDir "${ServerIP}_deployment_report_$(Get-Date -Format 'yyyyMMdd_HHmmss').md"
$ReportContent | Out-File -FilePath $ReportFile -Encoding UTF8 -Force
Write-Log "Deployment report generated: $ReportFile" "OK"
# Completion
Write-Log "`n========================================" "OK"
Write-Log "Deployment check completed!" "OK"
Write-Log "========================================" "OK"
# Monitor All Systems Deployment
$PlinkPath = "E:\GithubData\ubains-module-test\AuxiliaryTool\ScriptTool\RemoteDeploy\plink.exe"
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Monitoring All Systems Deployment" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
function Invoke-SSH {
param([string]$Command)
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw Ubains@123 -P 22 root@192.168.5.52 $Command"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit(60000)
return $p.StandardOutput.ReadToEnd()
}
# Check if deployment script is still running
$running = Invoke-SSH -Command "ps aux | grep deploy_all_complete | grep -v grep | wc -l"
if ($running.Trim() -eq "1") {
Write-Host "Deployment Status: RUNNING" -ForegroundColor Green
Write-Host ""
# Show recent log lines
Write-Host "Recent deployment log:" -ForegroundColor Gray
Write-Host "========================================" -ForegroundColor Gray
$log = Invoke-SSH -Command "tail -30 /data/offline_auto_unifiedPlatform/new_auto_script.log 2>/dev/null || tail -30 /var/log/deploy/deploy.log 2>/dev/null || echo 'Log not available'"
Write-Host $log
} else {
Write-Host "Deployment Status: COMPLETED or NOT RUNNING" -ForegroundColor Yellow
Write-Host ""
# Show full log
Write-Host "Full deployment log:" -ForegroundColor Gray
Write-Host "========================================" -ForegroundColor Gray
$log = Invoke-SSH -Command "tail -100 /data/offline_auto_unifiedPlatform/new_auto_script.log 2>/dev/null || tail -100 /var/log/deploy/deploy.log 2>/dev/null"
Write-Host $log
}
Write-Host ""
Write-Host "========================================" -ForegroundColor Gray
Write-Host "Services Status:" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Gray
# Check Docker containers
$docker = Invoke-SSH -Command "docker ps --format 'table {{.Names}}\t{{.Status}}' 2>/dev/null || echo 'Docker not available'"
Write-Host $docker
Write-Host ""
Write-Host "========================================" -ForegroundColor Gray
Write-Host "Java Services:" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Gray
# Check Java processes
$java = Invoke-SSH -Command "ps aux | grep java | grep -v grep | wc -l"
Write-Host "Total Java processes: $($java.Trim())" -ForegroundColor Cyan
Write-Host ""
Write-Host "========================================" -ForegroundColor Gray
Write-Host "Quick Commands:" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Gray
Write-Host "SSH to server: ssh root@192.168.5.52" -ForegroundColor White
Write-Host "Monitor deployment log: tail -f /data/offline_auto_unifiedPlatform/new_auto_script.log" -ForegroundColor White
Write-Host "Check services: docker ps" -ForegroundColor White
Write-Host "========================================" -ForegroundColor Gray
# Simple Deployment Monitor
$PlinkPath = "E:\GithubData\ubains-module-test\AuxiliaryTool\ScriptTool\RemoteDeploy\plink.exe"
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Deployment Status Monitor" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
function Invoke-SSH {
param([string]$Command)
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw Ubains@123 -P 22 root@192.168.5.52 $Command"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit(60000)
return $p.StandardOutput.ReadToEnd()
}
# Check if deployment is still running
$running = Invoke-SSH -Command "ps aux | grep new_auto.sh | grep -v grep | wc -l"
if ($running.Trim() -eq "1") {
Write-Host "Deployment Status: RUNNING" -ForegroundColor Green
} else {
Write-Host "Deployment Status: COMPLETED or STOPPED" -ForegroundColor Yellow
}
Write-Host ""
# Show recent log output
Write-Host "Recent deployment log (last 30 lines):" -ForegroundColor Gray
Write-Host "========================================" -ForegroundColor Gray
$log = Invoke-SSH -Command "tail -30 /var/log/deploy/deploy.log 2>/dev/null || tail -30 /data/logs/new_auto_script.log 2>/dev/null || echo 'Log not found'"
Write-Host $log
Write-Host ""
Write-Host "========================================" -ForegroundColor Gray
Write-Host "Quick Commands:" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Gray
Write-Host "SSH to server: ssh root@192.168.5.52" -ForegroundColor White
Write-Host "Monitor log: tail -f /var/log/deploy/deploy.log" -ForegroundColor White
Write-Host "Check process: ps aux | grep new_auto.sh" -ForegroundColor White
Write-Host "Check Docker: docker ps" -ForegroundColor White
Write-Host "========================================" -ForegroundColor Gray
import paramiko
import time
import sys
from datetime import datetime
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.5.52', username='root', password='Ubains@123', timeout=30)
# 启动部署脚本
print('[{}] 启动部署脚本: new_auto.sh --all'.format(datetime.now().strftime('%H:%M:%S')))
stdin, stdout, stderr = client.exec_command(
'cd /data/offline_auto_unifiedPlatform && ./new_auto.sh --all',
get_pty=True,
timeout=3600
)
# 监控输出
last_output = time.time()
while True:
if stdout.channel.exit_status_ready():
exit_code = stdout.channel.exit_status
print('[{}] 部署脚本退出,退出码: {}'.format(datetime.now().strftime('%H:%M:%S'), exit_code))
break
try:
if stdout.channel.recv_ready():
chunk = stdout.channel.recv(4096).decode('utf-8', errors='ignore')
for line in chunk.split('
'):
if any(kw in line for kw in ['部署', '安装', '完成', '错误', '容器', 'ERROR', '服务']):
print('[部署] {}'.format(line.strip()))
last_output = time.time()
except:
pass
if time.time() - last_output > 300:
elapsed = int((time.time() - start_time) / 60) if 'start_time' in locals() else 0
print('[{}] 部署进行中... 约{}分钟'.format(datetime.now().strftime('%H:%M:%S'), elapsed))
last_output = time.time()
time.sleep(5)
client.close()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
部署进度监控脚本
"""
import paramiko
import time
import sys
from datetime import datetime
def check_deployment_status():
"""检查部署状态"""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.5.52', username='root', password='Ubains@123', timeout=30)
print(f"\n{'='*70}")
print(f"部署进度监控 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"{'='*70}")
# 1. 检查脚本进程
stdin, stdout, stderr = client.exec_command('ps aux | grep new_auto.sh | grep -v grep')
process_info = stdout.read().decode('utf-8', errors='ignore').strip()
if process_info:
print("[进程] 部署脚本正在运行")
# 解析CPU和内存使用
parts = process_info.split()
if len(parts) >= 10:
cpu = parts[2]
mem = parts[3]
print(f" CPU: {cpu}, 内存: {mem}")
else:
print("[进程] 部署脚本已结束或未运行")
# 2. 检查Docker容器
stdin, stdout, stderr = client.exec_command('docker ps --format "{{.Names}}" 2>/dev/null | wc -l')
container_count = int(stdout.read().decode().strip())
print(f"[容器] 运行中: {container_count} 个")
if container_count > 0:
stdin, stdout, stderr = client.exec_command('docker ps --format "table {{.Names}}\t{{.Status}}"')
containers = stdout.read().decode('utf-8', errors='ignore')
print("\n容器列表:")
for line in containers.split('\n')[:11]: # 最多显示10个
if line.strip():
print(f" {line}")
# 3. 检查服务日志
log_paths = [
("预定对外", "/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"),
]
print("\n[日志] 服务状态检查:")
for service_name, log_path in log_paths:
stdin, stdout, stderr = client.exec_command(f'tail -50 {log_path} 2>/dev/null | grep -i "SYSTEMVERSION\\|启动\\|started" || echo "未找到"')
result = stdout.read().decode('utf-8', errors='ignore').strip()
if 'SYSTEMVERSION' in result or '启动' in result:
print(f" {service_name}: ✓ 服务已启动")
elif result == "未找到":
print(f" {service_name}: 等待启动...")
else:
print(f" {service_name}: 检查中...")
# 4. 检查网络端口
print("\n[网络] 端口监听状态:")
ports = [
("预定对外", 8080),
("预定对内", 8081),
("运维服务", 8002),
("讯飞服务", 8003),
]
for service_name, port in ports:
stdin, stdout, stderr = client.exec_command(f'netstat -tlnp 2>/dev/null | grep ":{port}" || echo ""')
result = stdout.read().decode('utf-8', errors='ignore').strip()
if result:
print(f" {service_name} (端口{port}): ✓ 监听中")
else:
print(f" {service_name} (端口{port}): 未监听")
client.close()
def main():
print("开始监控部署进度...")
print("按 Ctrl+C 停止监控")
check_interval = 60 # 每分钟检查一次
count = 0
max_checks = 60 # 最多监控60分钟
try:
while count < max_checks:
check_deployment_status()
count += 1
if count < max_checks:
print(f"\n等待 {check_interval} 秒后下次检查... ({count}/{max_checks})")
time.sleep(check_interval)
print("\n监控达到最大时长,结束监控")
except KeyboardInterrupt:
print("\n\n监控已停止")
if __name__ == '__main__':
main()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
部署监控脚本 - 实时监控部署进度
"""
import sys
import time
import subprocess
from datetime import datetime, timedelta
def run_ssh_command(command):
"""执行SSH命令"""
plink_path = r"E:\GithubData\ubains-module-test\AuxiliaryTool\ScriptTool\RemoteDeploy\plink.exe"
psi = subprocess.Popen(
[plink_path, "-pw", "Ubains@123", "-P", "22", "root@192.168.5.52", command],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
creationflags=subprocess.CREATE_NO_WINDOW
)
stdout, stderr = psi.communicate(timeout=30)
return stdout.decode('utf-8', errors='ignore'), stderr.decode('utf-8', errors='ignore')
def main():
print("=" * 50)
print("部署进度监控")
print("=" * 50)
print(f"开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print()
start_time = time.time()
max_monitor_time = 2700 # 45分钟监控时间
check_count = 0
while time.time() - start_time < max_monitor_time:
check_count += 1
current_time = datetime.now().strftime('%H:%M:%S')
elapsed = int(time.time() - start_time)
print(f"\n[{current_time}] 检查 #{check_count} (已监控: {elapsed}秒/{int(max_monitor_time/60)}分钟)")
print("-" * 50)
try:
# 检查部署进程
stdout, stderr = run_ssh_command('ps aux | grep new_auto | grep -v grep')
if 'new_auto.sh' in stdout:
# 解析进程信息
lines = stdout.strip().split('\n')
for line in lines:
if 'new_auto.sh' in line:
parts = line.split()
if len(parts) >= 9:
pid = parts[1]
cpu = parts[2]
mem = parts[3]
print(f"[运行中] PID: {pid}, CPU: {cpu}%, MEM: {mem}%")
else:
print("[完成] 部署进程已结束")
break
# 检查容器状态
stdout, stderr = run_ssh_command('docker ps --format "{{.Names}}"')
containers = [line for line in stdout.strip().split('\n') if line]
container_count = len(containers)
if container_count > 0:
print(f"[容器] 运行中: {container_count}个")
for container in containers[:10]: # 最多显示10个
print(f" - {container}")
else:
print("[容器] 尚未启动")
# 检查Docker镜像
stdout, stderr = run_ssh_command('docker images --format "{{.Repository}}" | grep -E "ubains|meeting|monitor" | wc -l')
image_count = stdout.strip()
print(f"[镜像] 已下载: {image_count}个")
# 预计完成时间
if container_count >= 5:
print("\n[SUCCESS] 部署成功!已启动所有容器")
break
elif container_count > 0:
remaining_time = max_monitor_time - elapsed
estimated_minutes = int(remaining_time / 60)
print(f"[进度] 容器启动中... 预计还需{estimated_minutes}分钟")
else:
remaining_time = max_monitor_time - elapsed
estimated_minutes = int(remaining_time / 60)
print(f"[进度] 正在部署... 预计还需{estimated_minutes}分钟")
except Exception as e:
print(f"[ERROR] 检查失败: {str(e)}")
# 等待30秒后再次检查
print("\n等待30秒后继续监控...")
time.sleep(30)
# 最终状态检查
print("\n" + "=" * 50)
print("部署完成 - 最终状态")
print("=" * 50)
try:
# 容器状态
stdout, stderr = run_ssh_command('docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"')
print("\n容器详细状态:")
print(stdout)
# 服务状态
stdout, stderr = run_ssh_command('docker ps | wc -l')
final_count = int(stdout.strip()) - 1
print(f"\n运行中的容器总数: {final_count}")
if final_count >= 5:
print("\n[SUCCESS] 部署成功完成")
print("\n后续步骤:")
print("1. 系统授权: 访问 https://192.168.5.52/#/LoginConfig")
print(" 账号: superadmin / Ubains@1357")
print(" 验证码: csba")
print("\n2. 创建管理员: 为'自动化'公司创建admin用户")
print("\n3. 验收测试: 检查服务接口")
return 0
else:
print("\n[WARN] 部署未完全完成,请检查日志")
return 1
except Exception as e:
print(f"\n[ERROR] 最终状态检查失败: {str(e)}")
return 1
if __name__ == '__main__':
sys.exit(main())
$PlinkPath = "E:\GithubData\ubains-module-test\AuxiliaryTool\ScriptTool\RemoteDeploy\plink.exe"
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw Ubains@123 -P 22 root@192.168.5.52 'ps aux | grep new_auto.sh | grep -v grep && echo ---RUNNING--- || echo ---COMPLETED---'"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit(60000)
$result = $p.StandardOutput.ReadToEnd()
Write-Host $result
# Re-run Deployment Script with Full System Selection
$PlinkPath = "E:\GithubData\ubains-module-test\AuxiliaryTool\ScriptTool\RemoteDeploy\plink.exe"
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Re-running Deployment with System Selection" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "This will connect to the server and run the deployment script interactively." -ForegroundColor Yellow
Write-Host "When prompted to select systems, please choose '全部系统' (All Systems)" -ForegroundColor Yellow
Write-Host ""
Write-Host "Press Enter to continue..." -ForegroundColor Gray
Read-Host
Write-Host ""
Write-Host "Connecting to server 192.168.5.52..." -ForegroundColor Cyan
Write-Host "You will be prompted for deployment options in the SSH session." -ForegroundColor Yellow
Write-Host ""
# Start interactive SSH session
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw Ubains@123 -P 22 root@192.168.5.52"
$psi.UseShellExecute = $true
$psi.RedirectStandardOutput = $false
$psi.RedirectStandardError = $false
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit()
Write-Host ""
Write-Host "========================================" -ForegroundColor Green
Write-Host "SSH session completed" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
远程执行部署脚本
"""
import paramiko
import time
import sys
from datetime import datetime
def run_deployment():
"""执行部署脚本"""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.5.52', username='root', password='Ubains@123', timeout=30)
print("=" * 70)
print("开始执行部署: new_auto.sh --all")
print(f"时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("=" * 70)
# 使用invoke_shell来执行交互式脚本
channel = client.invoke_shell()
channel.settimeout(300)
# 发送命令
time.sleep(1)
channel.send("cd /data/offline_auto_unifiedPlatform\n")
time.sleep(2)
channel.send("./new_auto.sh --all\n")
print("部署脚本已启动,开始监控输出...\n")
output_file = f"reports/192.168.5.52_deploy_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
# 监控输出
start_time = time.time()
last_progress_time = time.time()
buffer = ""
try:
while True:
if channel.exit_status_ready():
exit_code = channel.recv_exit_status()
print(f"\n[完成] 部署脚本退出,退出码: {exit_code}")
break
try:
if channel.recv_ready():
chunk = channel.recv(4096).decode('utf-8', errors='ignore')
buffer += chunk
# 实时打印关键信息
for line in chunk.split('\n'):
line = line.strip()
if line and any(kw in line for kw in [
'部署', '安装', '启动', '完成', '成功',
'失败', '错误', '容器', 'Docker', '服务',
'ERROR', 'WARN', 'INFO', '系统',
'middleware', 'database', 'redis', 'nginx'
]):
timestamp = datetime.now().strftime('%H:%M:%S')
print(f"[{timestamp}] {line}")
# 保存到文件
import os
os.makedirs('reports', exist_ok=True)
with open(output_file, 'a', encoding='utf-8') as f:
f.write(chunk)
except Exception as e:
pass
# 每分钟输出进度
elapsed = int(time.time() - start_time)
if elapsed > 0 and elapsed % 60 == 0:
progress_time = time.time()
if progress_time - last_progress_time >= 55:
print(f"\n[进度] 部署进行中... 已用时: {int(elapsed/60)}分钟")
last_progress_time = progress_time
# 超时检查(45分钟)
if elapsed > 2700:
print("\n[警告] 部署超时")
break
time.sleep(2)
except KeyboardInterrupt:
print("\n\n[中断] 部署被用户中断")
finally:
channel.close()
client.close()
total_time = int((time.time() - start_time) / 60)
print(f"\n部署执行完成,总用时: {total_time} 分钟")
print(f"日志已保存到: {output_file}")
return 0
if __name__ == '__main__':
sys.exit(run_deployment())
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
简单部署测试 - 仅测试部署准备
"""
import sys
import os
# 添加当前目录到路径
sys.path.insert(0, os.path.dirname(__file__))
from auto_deployment_python import RemoteDeploymentAutomation
def main():
print("部署准备测试")
print("=" * 50)
config = {
'host': '192.168.5.52',
'username': 'root',
'password': 'Ubains@123',
'license_path': r'E:\自动化部署\X86-5.52\license.zip'
}
deployment = RemoteDeploymentAutomation(**config)
# 测试SSH连接
print("测试SSH连接...")
if deployment.connect_ssh():
print("[OK] SSH连接成功")
# 测试环境准备
print("测试环境准备...")
if deployment.prepare_deployment_environment():
print("[OK] 环境准备完成")
# 测试交互式连接
print("测试交互式连接...")
if deployment.connect_ssh_interactive():
print("[OK] 交互式连接成功")
# 发送测试命令
print("发送测试命令...")
deployment.ssh_shell.send("echo 'Test successful'\n")
import time
time.sleep(2)
# 读取响应
output = ""
try:
while deployment.ssh_shell.recv_ready():
output += deployment.ssh_shell.recv(4096).decode('utf-8', errors='ignore')
except:
pass
if 'Test successful' in output:
print("[OK] 测试命令执行成功")
print("响应:", output.strip())
else:
print("[ERROR] 测试命令执行失败")
print("输出:", output)
else:
print("[ERROR] 交互式连接失败")
else:
print("[ERROR] 环境准备失败")
deployment.ssh_client.close()
return 0
else:
print("[ERROR] SSH连接失败")
return 1
if __name__ == '__main__':
sys.exit(main())
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
部署脚本测试 - 验证基本功能
"""
import sys
import os
# 添加当前目录到路径
sys.path.insert(0, os.path.dirname(__file__))
from auto_deployment_python import RemoteDeploymentAutomation
def test_ssh_connection():
"""测试SSH连接"""
print("=" * 50)
print("测试1: SSH连接")
print("=" * 50)
config = {
'host': '192.168.5.52',
'username': 'root',
'password': 'Ubains@123',
'license_path': r'E:\自动化部署\X86-5.52\license.zip'
}
deployment = RemoteDeploymentAutomation(**config)
# 测试paramiko连接
if deployment.connect_ssh():
print("[OK] SSH连接成功 (paramiko)")
# 测试环境准备
if deployment.prepare_deployment_environment():
print("[OK] 部署环境检查完成")
# 检查部署脚本
stdin, stdout, stderr = deployment.ssh_client.exec_command('ls -la /data/offline_auto_unifiedPlatform/*.sh')
scripts = stdout.read().decode('utf-8', errors='ignore')
print("\n部署脚本:")
print(scripts)
deployment.ssh_client.close()
return True
else:
print("[ERROR] SSH连接失败")
return False
def test_deployment_script_status():
"""测试部署脚本状态"""
print("\n" + "=" * 50)
print("测试2: 部署脚本状态")
print("=" * 50)
config = {
'host': '192.168.5.52',
'username': 'root',
'password': 'Ubains@123',
'license_path': r'E:\自动化部署\X86-5.52\license.zip'
}
deployment = RemoteDeploymentAutomation(**config)
if deployment.connect_ssh():
# 检查部署脚本权限
stdin, stdout, stderr = deployment.ssh_client.exec_command('ls -l /data/offline_auto_unifiedPlatform/new_auto.sh')
script_info = stdout.read().decode('utf-8', errors='ignore')
print(f"部署脚本信息: {script_info.strip()}")
# 检查是否有运行中的部署进程
stdin, stdout, stderr = deployment.ssh_client.exec_command('ps aux | grep new_auto | grep -v grep')
running_processes = stdout.read().decode('utf-8', errors='ignore')
if running_processes.strip():
print("[WARN] 检测到运行中的部署进程:")
print(running_processes)
else:
print("[OK] 无运行中的部署进程")
deployment.ssh_client.close()
return True
return False
def test_web_connectivity():
"""测试Web连接"""
print("\n" + "=" * 50)
print("测试3: Web连接")
print("=" * 50)
import requests
requests.packages.urllib3.disable_warnings()
config = {
'host': '192.168.5.52',
'username': 'root',
'password': 'Ubains@123',
'license_path': r'E:\自动化部署\X86-5.52\license.zip'
}
deployment = RemoteDeploymentAutomation(**config)
# 测试维护平台连接
urls = [
('维护平台', 'https://192.168.5.52/#/LoginConfig'),
('后台管理', 'https://192.168.5.52/#/LoginAdmin'),
('前台页面', 'https://192.168.5.52/'),
]
for name, url in urls:
try:
response = requests.get(url, verify=False, timeout=10)
if response.status_code == 200:
print(f"[OK] {name}: 可访问 ({url})")
else:
print(f"[WARN] {name}: 状态码 {response.status_code}")
except Exception as e:
print(f"[ERROR] {name}: {str(e)}")
return True
def main():
"""主测试函数"""
print("Python自动化部署脚本 - 功能测试")
print("目标服务器: 192.168.5.52")
print()
results = []
# 测试SSH连接
results.append(("SSH连接", test_ssh_connection()))
# 测试部署脚本状态
results.append(("部署脚本状态", test_deployment_script_status()))
# 测试Web连接
results.append(("Web连接", test_web_connectivity()))
# 输出测试结果
print("\n" + "=" * 50)
print("测试结果汇总")
print("=" * 50)
for name, result in results:
status = "[OK] PASS" if result else "[ERROR] FAIL"
print(f"{name}: {status}")
all_passed = all(result for _, result in results)
if all_passed:
print("\n[OK] 所有测试通过!可以执行完整部署。")
else:
print("\n[WARN] 部分测试失败,请检查环境配置。")
return 0 if all_passed else 1
if __name__ == '__main__':
sys.exit(main())
# Upload and Deploy Script
# Author: Automation Team
# Date: 2026-05-14
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$PackagesDir = Join-Path $ScriptDir "packages"
$ReportsDir = Join-Path $ScriptDir "reports"
# Create directories
if (-not (Test-Path $PackagesDir)) { New-Item -ItemType Directory -Path $PackagesDir -Force | Out-Null }
if (-not (Test-Path $ReportsDir)) { New-Item -ItemType Directory -Path $ReportsDir -Force | Out-Null }
$LogFile = Join-Path $ReportsDir "upload_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
function Write-Log {
param([string]$Message, [string]$Color = "White")
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogMessage = "[$Timestamp] $Message"
Write-Host $LogMessage -ForegroundColor $Color
Add-Content -Path $LogFile -Value $LogMessage
}
function Invoke-SSHCommand {
param([string]$Command)
$PlinkPath = Join-Path $ScriptDir "plink.exe"
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw $Password -P $SSHPort ${Username}@${ServerIP} $Command"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit(60000)
return $p.StandardOutput.ReadToEnd()
}
function Upload-File {
param([string]$LocalPath, [string]$RemotePath)
$PscpPath = Join-Path $ScriptDir "pscp.exe"
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PscpPath
$psi.Arguments = "-pw $Password -P $SSHPort -batch '$LocalPath' '${Username}@${ServerIP}:${RemotePath}'"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit(300000)
return $p.ExitCode -eq 0
}
# Configuration
$ServerIP = "192.168.5.52"
$Username = "root"
$Password = "Ubains@123"
$SSHPort = 22
# Network share path
$NetworkShare = "\\192.168.9.9\发布版本\03服务器部署\临时使用-新统一平台\X86部署包\全量版"
Write-Log "========================================" "Cyan"
Write-Log "Upload and Deploy Script" "Cyan"
Write-Log "========================================" "Cyan"
# Step 1: Copy from network share
Write-Log "Step 1: Copying deployment package from network share..." "Yellow"
Write-Log "Source: $NetworkShare" "Gray"
if (-not (Test-Path $NetworkShare)) {
Write-Log "Network share path not accessible!" "Red"
Write-Log "Please ensure:" "Yellow"
Write-Log "1. You are connected to the company network" "Yellow"
Write-Log "2. You have permission to access the share" "Yellow"
Write-Log "3. The network path is correct" "Yellow"
exit 1
}
# Clean local packages directory
if (Test-Path $PackagesDir) {
Remove-Item -Path "$PackagesDir\*" -Recurse -Force -ErrorAction SilentlyContinue
}
# Copy from network share
Write-Log "Copying files from network share (this may take a while)..." "Yellow"
try {
$Files = Get-ChildItem -Path $NetworkShare -Recurse -File -ErrorAction Stop
$TotalFiles = $Files.Count
$CopiedFiles = 0
foreach ($File in $Files) {
$RelativePath = $File.FullName.Substring($NetworkShare.Length + 1)
$DestPath = Join-Path $PackagesDir $RelativePath
$DestDir = Split-Path $DestPath
if (-not (Test-Path $DestDir)) {
New-Item -ItemType Directory -Path $DestDir -Force | Out-Null
}
Copy-Item -Path $File.FullName -Destination $DestPath -Force
$CopiedFiles++
if ($CopiedFiles % 10 -eq 0) {
Write-Progress -Activity "Copying deployment package" -Status "$CopiedFiles / $TotalFiles files" -PercentComplete (($CopiedFiles / $TotalFiles) * 100)
}
}
Write-Progress -Activity "Copying deployment package" -Completed
Write-Log "Copied $CopiedFiles files from network share" "Green"
$LocalPackageDir = $PackagesDir
}
catch {
Write-Log "Failed to copy from network share: $_" "Red"
Write-Log "Trying to list top-level directory..." "Yellow"
try {
$TopItems = Get-ChildItem -Path $NetworkShare -ErrorAction Stop
Write-Log "Found items in network share:" "Gray"
foreach ($Item in $TopItems) {
Write-Log " - $($Item.Name) ($($Item.Length) bytes)" "Gray"
}
}
catch {
Write-Log "Cannot access network share" "Red"
}
exit 1
}
# Step 2: Create deploy directory on server
Write-Log "`nStep 2: Creating deploy directory on server..." "Yellow"
Invoke-SSHCommand -Command "mkdir -p /home/deploy"
Write-Log "Deploy directory created" "Green"
# Step 3: Upload deployment package
Write-Log "`nStep 3: Uploading deployment package to server..." "Yellow"
$UploadFiles = Get-ChildItem -Path $LocalPackageDir -Recurse -File
$TotalUpload = $UploadFiles.Count
$UploadedCount = 0
$FailedUploads = @()
foreach ($File in $UploadFiles) {
$RelativePath = $File.FullName.Substring($LocalPackageDir.Length + 1)
$RemotePath = "/home/deploy/$RelativePath"
$RemoteDir = "/home/deploy/" + (Split-Path $RelativePath -Parent)
# Create remote directory
Invoke-SSHCommand -Command "mkdir -p '$RemoteDir'"
# Upload file
$Success = Upload-File -LocalPath $File.FullName -RemotePath $RemotePath
if ($Success) {
$UploadedCount++
} else {
$FailedUploads += $RelativePath
}
if ($UploadedCount % 10 -eq 0) {
Write-Progress -Activity "Uploading to server" -Status "$UploadedCount / $TotalUpload files" -PercentComplete (($UploadedCount / $TotalUpload) * 100)
}
}
Write-Progress -Activity "Uploading to server" -Completed
Write-Log "Uploaded $UploadedCount files to server" "Green"
if ($FailedUploads.Count -gt 0) {
Write-Log "Failed to upload $($FailedUploads.Count) files:" "Yellow"
foreach ($Failed in $FailedUploads) {
Write-Log " - $Failed" "Gray"
}
}
# Step 4: Check uploaded files
Write-Log "`nStep 4: Verifying uploaded files..." "Yellow"
$ServerFiles = Invoke-SSHCommand -Command "find /home/deploy -type f | wc -l"
Write-Log "Files on server: $ServerFiles" "Green"
# Step 5: Find deployment script
Write-Log "`nStep 5: Looking for deployment script..." "Yellow"
$DeployScripts = Invoke-SSHCommand -Command "find /home/deploy -name '*.sh' -type f 2>/dev/null | head -10"
Write-Log "Found deployment scripts:" "Gray"
Write-Host $DeployScripts.Output
Write-Log "`n========================================" "Green"
Write-Log "Upload completed!" "Green"
Write-Log "========================================" "Green"
Write-Log "Next steps:" "Yellow"
Write-Log "1. SSH to server: ssh root@${ServerIP}" "Gray"
Write-Log "2. Go to deploy directory: cd /home/deploy" "Gray"
Write-Log "3. Run deployment script" "Gray"
Write-Log "========================================" "Green"
@echo off
setlocal enabledelayedexpansion
REM ========================================
REM Upload and Deploy Script
REM ========================================
set SCRIPT_DIR=%~dp0
set PACKAGES_DIR=%SCRIPT_DIR%packages
set REPORTS_DIR=%SCRIPT_DIR%reports
set SERVER_IP=192.168.5.52
set USERNAME=root
set PASSWORD=Ubains@123
set SSH_PORT=22
set NETWORK_SHARE=\\192.168.9.9\发布版本\03服务器部署\临时使用-新统一平台\X86部署包\全量版
echo ========================================
echo Upload and Deploy Script
echo ========================================
echo.
REM Create directories
if not exist "%PACKAGES_DIR%" mkdir "%PACKAGES_DIR%"
if not exist "%REPORTS_DIR%" mkdir "%REPORTS_DIR%"
REM Step 1: Check network share
echo Step 1: Checking network share...
echo Source: %NETWORK_SHARE%
if not exist "%NETWORK_SHARE%" (
echo ERROR: Network share not accessible!
echo.
echo Possible reasons:
echo 1. Not connected to company network
echo 2. No permission to access share
echo 3. Network path is incorrect
pause
exit /b 1
)
echo OK: Network share is accessible
echo.
REM Step 2: List files
echo Step 2: Listing files in network share...
dir "%NETWORK_SHARE%" /b
echo.
REM Step 3: Copy files locally
echo Step 3: Copying files locally...
echo This may take a while...
robocopy "%NETWORK_SHARE%" "%PACKAGES_DIR%" /E /NFL /NDL /NJH /NJS
if %ERRORLEVEL% LSS 8 (
echo OK: Files copied locally
) else (
echo WARNING: Robocopy reported some issues
)
echo.
REM Step 4: Create deploy directory on server
echo Step 4: Creating deploy directory on server...
plink.exe -pw %PASSWORD% -P %SSH_PORT% %USERNAME%@%SERVER_IP% "mkdir -p /home/deploy && echo 'OK'"
echo.
echo.
REM Step 5: Upload files to server
echo Step 5: Uploading files to server...
echo This may take a long time depending on file size...
echo.
echo Using pscp to upload files...
pscp.exe -pw %PASSWORD% -P %SSH_PORT% -batch -r "%PACKAGES_DIR%\*" %USERNAME%@%SERVER_IP%:/home/deploy/
echo.
echo Upload completed
echo.
REM Step 6: Verify upload
echo Step 6: Verifying upload...
plink.exe -pw %PASSWORD% -P %SSH_PORT% %USERNAME%@%SERVER_IP% "find /home/deploy -type f | wc -l"
echo.
REM Step 7: Find deployment scripts
echo Step 7: Looking for deployment scripts...
plink.exe -pw %PASSWORD% -P %SSH_PORT% %USERNAME%@%SERVER_IP% "find /home/deploy -name '*.sh' -type f 2>/dev/null | head -10"
echo.
echo ========================================
echo Upload completed!
echo ========================================
echo.
echo Next steps to complete deployment:
echo 1. SSH to server: ssh root@%SERVER_IP%
echo 2. Go to deploy directory: cd /home/deploy
echo 3. Find and run the deployment script
echo 4. Follow the deployment prompts
echo.
echo After deployment completes:
echo 1. Access maintenance platform: https://%SERVER_IP%/#/LoginConfig
echo 2. Enter verification code: csba
echo 3. Upload license file from network share
echo ========================================
echo.
pause
# Upload and Deploy Script - Simplified
# Author: Automation Team
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$PackagesDir = Join-Path $ScriptDir "packages"
$ReportsDir = Join-Path $ScriptDir "reports"
if (-not (Test-Path $PackagesDir)) { New-Item -ItemType Directory -Path $PackagesDir -Force | Out-Null }
if (-not (Test-Path $ReportsDir)) { New-Item -ItemType Directory -Path $ReportsDir -Force | Out-Null }
function Write-Log {
param([string]$Message, [string]$Color = "White")
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Write-Host "[$Timestamp] $Message" -ForegroundColor $Color
}
function Invoke-SSHCommand {
param([string]$Command)
$PlinkPath = Join-Path $ScriptDir "plink.exe"
$Password = "Ubains@123"
$SSHPort = 22
$ServerIP = "192.168.5.52"
$Username = "root"
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PlinkPath
$psi.Arguments = "-pw $Password -P $SSHPort ${Username}@${ServerIP} $Command"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit(60000)
return $p.StandardOutput.ReadToEnd()
}
function Upload-File {
param([string]$LocalPath, [string]$RemotePath)
$PscpPath = Join-Path $ScriptDir "pscp.exe"
$Password = "Ubains@123"
$SSHPort = 22
$ServerIP = "192.168.5.52"
$Username = "root"
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $PscpPath
$psi.Arguments = "-pw $Password -P $SSHPort -batch '$LocalPath' '${Username}@${ServerIP}:${RemotePath}'"
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
$p.WaitForExit(300000)
return $p.ExitCode -eq 0
}
# Network share path (using single quotes to avoid encoding issues)
$NetworkShare = '\\192.168.9.9\发布版本\03服务器部署\临时使用-新统一平台\X86部署包\全量版'
Write-Log "========================================" "Cyan"
Write-Log "Upload and Deploy Script" "Cyan"
Write-Log "========================================" "Cyan"
# Step 1: Check network share
Write-Log "Step 1: Checking network share..." "Yellow"
Write-Log "Source: $NetworkShare" "Gray"
if (-not (Test-Path $NetworkShare)) {
Write-Log "ERROR: Network share not accessible!" "Red"
Write-Log "" "Yellow"
Write-Log "Possible reasons:" "Yellow"
Write-Log "1. Not connected to company network" "Gray"
Write-Log "2. No permission to access share" "Gray"
Write-Log "3. Network path is incorrect" "Gray"
Write-Log "" "Yellow"
Write-Log "Please check the path and try again." "Yellow"
Read-Host "Press Enter to exit"
exit 1
}
Write-Log "Network share is accessible" "Green"
# Step 2: List files in network share
Write-Log "" "Yellow"
Write-Log "Step 2: Listing files in network share..." "Yellow"
try {
$Items = Get-ChildItem -Path $NetworkShare -ErrorAction Stop
Write-Log "Found $($Items.Count) items:" "Gray"
foreach ($Item in $Items) {
if ($Item.PSIsContainer) {
Write-Log " [DIR] $($Item.Name)" "Gray"
} else {
$Size = [math]::Round($Item.Length / 1MB, 2)
Write-Log " [FILE] $($Item.Name) ($Size MB)" "Gray"
}
}
}
catch {
Write-Log "ERROR: Failed to list files: $_" "Red"
Read-Host "Press Enter to exit"
exit 1
}
# Step 3: Create deploy directory on server
Write-Log "" "Yellow"
Write-Log "Step 3: Creating deploy directory on server..." "Yellow"
$Result = Invoke-SSHCommand -Command "mkdir -p /home/deploy && echo 'OK'"
if ($Result -match "OK") {
Write-Log "Deploy directory created successfully" "Green"
} else {
Write-Log "ERROR: Failed to create deploy directory" "Red"
Read-Host "Press Enter to exit"
exit 1
}
# Step 4: Upload deployment package
Write-Log "" "Yellow"
Write-Log "Step 4: Uploading deployment package..." "Yellow"
Write-Log "This may take a while depending on file size..." "Gray"
# Clean local packages directory
if (Test-Path $PackagesDir) {
Remove-Item -Path "$PackagesDir\*" -Recurse -Force -ErrorAction SilentlyContinue
}
# Copy files locally first (for faster processing)
Write-Log "Copying files locally first..." "Gray"
try {
robocopy $NetworkShare $PackagesDir /E /NFL /NDL /NJH /NJS | Out-Null
Write-Log "Files copied locally" "Green"
}
catch {
Write-Log "Warning: Robocopy had issues, trying alternative..." "Yellow"
Copy-Item -Path "$NetworkShare\*" -Destination $PackagesDir -Recurse -Force -ErrorAction SilentlyContinue
}
# Get files to upload
$UploadFiles = Get-ChildItem -Path $PackagesDir -Recurse -File
$TotalFiles = $UploadFiles.Count
$UploadedCount = 0
Write-Log "Total files to upload: $TotalFiles" "Gray"
# Upload files
foreach ($File in $UploadFiles) {
$RelativePath = $File.FullName.Substring($PackagesDir.Length + 1)
$RemotePath = "/home/deploy/$RelativePath"
$RemoteDir = Split-Path $RemotePath -Parent
# Create remote directory
Invoke-SSHCommand -Command "mkdir -p '$RemoteDir'" | Out-Null
# Upload file
$Success = Upload-File -LocalPath $File.FullName -RemotePath $RemotePath
if ($Success) {
$UploadedCount++
}
if ($UploadedCount % 50 -eq 0) {
$Percent = [math]::Round(($UploadedCount / $TotalFiles) * 100)
Write-Log "Progress: $UploadedCount / $TotalFiles ($Percent%)" "Gray"
}
}
Write-Log "Uploaded $UploadedCount files to server" "Green"
# Step 5: Verify upload
Write-Log "" "Yellow"
Write-Log "Step 5: Verifying upload..." "Yellow"
$ServerFiles = Invoke-SSHCommand -Command "find /home/deploy -type f | wc -l"
Write-Log "Files on server: $ServerFiles" "Green"
# Step 6: Find deployment scripts
Write-Log "" "Yellow"
Write-Log "Step 6: Looking for deployment scripts..." "Yellow"
$DeployScripts = Invoke-SSHCommand -Command "find /home/deploy -name '*.sh' -type f 2>/dev/null | head -10"
if ($DeployScripts) {
Write-Log "Found deployment scripts:" "Gray"
$DeployScripts -split "`n" | Where-Object { $_ -ne "" } | ForEach-Object {
Write-Log " $_" "Gray"
}
} else {
Write-Log "No deployment scripts found" "Yellow"
}
Write-Log "" "Green"
Write-Log "========================================" "Green"
Write-Log "Upload completed successfully!" "Green"
Write-Log "========================================" "Green"
Write-Log "" "Yellow"
Write-Log "Next steps to complete deployment:" "Yellow"
Write-Log "1. SSH to server: ssh root@192.168.5.52" "Gray"
Write-Log "2. Go to deploy directory: cd /home/deploy" "Gray"
Write-Log "3. Find and run the deployment script" "Gray"
Write-Log "4. Follow the deployment prompts" "Gray"
Write-Log "" "Gray"
Write-Log "After deployment completes:" "Yellow"
Write-Log "1. Access maintenance platform: https://192.168.5.52/#/LoginConfig" "Gray"
Write-Log "2. Enter verification code: csba" "Gray"
Write-Log "3. Upload license file from network share" "Gray"
Write-Log "========================================" "Green"
Read-Host "Press Enter to exit"
......@@ -3,12 +3,13 @@
"""
X86服务器远程自动化部署脚本
严格按照PRD文档和部署操作指导执行
禁止中断解压缩操作
"""
import sys
import os
import time
import subprocess
import socket
import paramiko
import requests
from datetime import datetime
......@@ -17,6 +18,14 @@ from urllib3.exceptions import InsecureRequestWarning
# 禁用SSL警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
# 修复Windows控制台编码问题
if sys.platform == 'win32':
try:
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
sys.stderr.reconfigure(encoding='utf-8', errors='replace')
except Exception:
pass
class X86AutoDeploy:
def __init__(self):
......@@ -24,31 +33,68 @@ class X86AutoDeploy:
self.username = 'root'
self.password = 'Ubains@123'
self.deploy_dir = '/data/offline_auto_unifiedPlatform'
self.deploy_log = '/data/offline_auto_unifiedPlatform/deploy_output.log'
self.ssh_client = None
self.deploy_start_time = None
self.total_start_time = None
self.deploy_start_time = None
self.log_file = None
self.license_path = r'E:\自动化部署\X86-5.52\license.zip'
self.admin_user = 'superadmin'
self.admin_pass = 'Ubains@1357'
def log(self, message, level="INFO", print_only=False):
"""输出日志"""
def log(self, message, level="INFO"):
"""输出日志到控制台和文件"""
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
log_msg = f"[{timestamp}] [{level}] {message}"
try:
print(log_msg)
if self.log_file and not print_only:
except UnicodeEncodeError:
safe_msg = log_msg.encode('gbk', errors='replace').decode('gbk')
print(safe_msg)
if self.log_file:
try:
with open(self.log_file, 'a', encoding='utf-8') as f:
f.write(log_msg + '\n')
except:
except Exception:
pass
def init_log_file(self):
"""初始化日志文件"""
reports_dir = os.path.join(os.path.dirname(__file__), 'reports')
reports_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'reports')
os.makedirs(reports_dir, exist_ok=True)
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
self.log_file = os.path.join(reports_dir, f'{self.host}_deploy_{timestamp}.log')
self.log(f"日志文件: {self.log_file}", print_only=True)
self.log(f"日志文件: {self.log_file}")
def exec_cmd(self, cmd, timeout=300):
"""执行SSH命令并等待返回"""
try:
stdin, stdout, stderr = self.ssh_client.exec_command(cmd, timeout=timeout)
out = stdout.read().decode('utf-8', errors='replace')
err = stderr.read().decode('utf-8', errors='replace')
exit_code = stdout.channel.recv_exit_status()
return exit_code, out, err
except Exception as e:
self.log(f"命令执行异常: {cmd[:80]}... -> {str(e)}", "ERROR")
return -1, '', str(e)
def exec_background(self, cmd):
"""执行后台命令,用独立通道避免阻塞,立即返回输出"""
transport = self.ssh_client.get_transport()
channel = transport.open_session()
channel.settimeout(15)
channel.exec_command(cmd)
output = ''
# 等待命令输出
time.sleep(3)
try:
if channel.recv_ready():
output = channel.recv(8192).decode('utf-8', errors='replace')
except socket.timeout:
pass
channel.close()
return output.strip()
def connect_ssh(self):
"""连接SSH"""
......@@ -70,332 +116,339 @@ class X86AutoDeploy:
self.log(f"SSH连接失败: {str(e)}", "ERROR")
return False
def cleanup_existing_processes(self):
"""清理现有部署进程"""
self.log("检查并清理现有部署进程...")
try:
commands = [
"pkill -9 -f new_auto.sh",
"sleep 2"
]
for cmd in commands:
stdin, stdout, stderr = self.ssh_client.exec_command(cmd)
stdout.read()
self.log("现有进程清理完成")
time.sleep(2)
return True
except Exception as e:
self.log(f"清理进程时出错: {str(e)}", "WARN")
def step1_check_disk(self):
"""步骤1:服务器硬盘检查"""
self.log("=" * 60)
self.log("【步骤1】服务器硬盘检查")
self.log("=" * 60)
code, out, err = self.exec_cmd("df -h /data")
self.log(f"磁盘状态:\n{out}")
if '/data' in out:
self.log("[OK] /data 分区存在")
return True
self.log("[FAIL] /data 分区不存在", "ERROR")
return False
def check_prerequisites(self):
"""检查前置条件"""
def step2_verify_package(self):
"""步骤2:校验部署包完整性"""
self.log("=" * 60)
self.log("检查前置条件")
self.log("【步骤2】校验部署包完整性")
self.log("=" * 60)
checks = []
# 1. 检查部署目录
self.log("1. 检查部署目录...")
try:
stdin, stdout, stderr = self.ssh_client.exec_command(
f"ls -la {self.deploy_dir} | head -20"
code, out, err = self.exec_cmd(
"ls -la /data/offline_auto_unifiedPlatform.tar.gz "
"/data/offline_auto_unifiedPlatform.tar.gz.md5 2>&1"
)
output = stdout.read().decode('utf-8', errors='ignore')
self.log(f"部署目录内容:\n{output}")
if 'new_auto.sh' in output:
self.log("[OK] 部署脚本存在")
checks.append(True)
else:
self.log("[FAIL] 部署脚本不存在", "ERROR")
checks.append(False)
except Exception as e:
self.log(f"[FAIL] 无法访问部署目录: {str(e)}", "ERROR")
checks.append(False)
self.log(f"文件列表:\n{out}")
# 2. 检查脚本权限
self.log("\n2. 检查脚本权限...")
try:
stdin, stdout, stderr = self.ssh_client.exec_command(
f"ls -l {self.deploy_dir}/new_auto.sh"
)
output = stdout.read().decode('utf-8', errors='ignore')
self.log(f"脚本权限: {output.strip()}")
if 'x' in output:
self.log("[OK] 脚本有执行权限")
checks.append(True)
else:
self.log("[WARN] 脚本无执行权限,正在添加...")
stdin, stdout, stderr = self.ssh_client.exec_command(
f"chmod 755 {self.deploy_dir}/new_auto.sh"
)
stdout.read()
self.log("[OK] 已添加执行权限")
checks.append(True)
except Exception as e:
self.log(f"[FAIL] 检查权限失败: {str(e)}", "ERROR")
checks.append(False)
if 'No such file' in out or '无法访问' in out:
self.log("[FAIL] 部署包文件不存在", "ERROR")
return False
# 3. 检查磁盘空间
self.log("\n3. 检查磁盘空间...")
try:
stdin, stdout, stderr = self.ssh_client.exec_command("df -h /data")
output = stdout.read().decode('utf-8', errors='ignore')
self.log(f"磁盘状态:\n{output}")
checks.append(True)
except Exception as e:
self.log(f"[WARN] 检查磁盘失败: {str(e)}", "WARN")
checks.append(True)
code, out, err = self.exec_cmd("cd /data && md5sum -c offline_auto_unifiedPlatform.tar.gz.md5")
self.log(f"MD5校验结果: {out.strip()}")
return all(checks)
if 'OK' in out or '成功' in out:
self.log("[OK] 部署包完整性校验通过")
return True
self.log("[WARN] MD5校验结果不确定,继续执行", "WARN")
return True
def execute_deployment(self):
"""执行部署脚本 new_auto.sh --all"""
def step3_extract_and_chmod(self):
"""步骤3:解压并赋权(禁止中断)"""
self.log("=" * 60)
self.log("开始执行部署脚本: new_auto.sh --all")
self.log("【步骤3】解压并赋权脚本")
self.log("【重要】解压过程禁止中断!")
self.log("=" * 60)
self.deploy_start_time = time.time()
try:
cmd = f"cd {self.deploy_dir} && ./new_auto.sh --all"
self.log(f"执行命令: {cmd}")
self.log("预计部署时间: 40分钟")
# 使用exec_command执行
stdin, stdout, stderr = self.ssh_client.exec_command(cmd, get_pty=True, timeout=2700)
# 监控部署过程
output_buffer = ""
last_log_time = time.time()
last_progress_time = time.time()
self.log("开始监控部署过程...")
# 检查是否已解压
code, out, err = self.exec_cmd(f"ls {self.deploy_dir}/new_auto.sh 2>&1")
if code == 0 and 'new_auto.sh' in out:
self.log("[OK] 部署目录已存在,跳过解压")
else:
self.log("开始解压部署包(后台执行,不会中断)...")
# 写一个解压脚本到服务器
extract_script = f"""#!/bin/bash
cd /data
tar -zxvf offline_auto_unifiedPlatform.tar.gz
echo "EXTRACT_DONE"
"""
self.exec_cmd(f"cat > /tmp/extract.sh << 'EXTRACT_EOF'\n{extract_script}\nEXTRACT_EOF")
self.exec_cmd("chmod +x /tmp/extract.sh")
while True:
# 检查进程状态
if stdout.channel.exit_status_ready():
exit_code = stdout.channel.exit_status
self.log(f"部署脚本进程已结束,退出码: {exit_code}")
# 后台执行解压
output = self.exec_background(
f"nohup /tmp/extract.sh </dev/null > /data/extract_output.log 2>&1 & echo $!"
)
pid = output.strip().split('\n')[-1].strip()
self.log(f"解压进程PID: {pid}")
if not pid or not pid.isdigit():
# 可能解压已经完成了,检查文件
code, out, err = self.exec_cmd(f"ls {self.deploy_dir}/new_auto.sh 2>&1")
if 'new_auto.sh' in out:
self.log("[OK] 解压已完成")
else:
# 等一下再试
time.sleep(10)
code, out, err = self.exec_cmd(f"pgrep -f 'tar -zxvf' | head -1")
pid = out.strip()
# 等待解压完成(最多20分钟)
max_wait = 1200
waited = 0
while waited < max_wait:
time.sleep(10)
waited += 10
# 检查extract_output.log是否包含完成标志
code, out, err = self.exec_cmd("grep 'EXTRACT_DONE' /data/extract_output.log 2>/dev/null && echo 'done' || echo 'running'")
if waited % 60 == 0:
self.log(f"解压进行中... 已等待 {waited}秒")
if 'done' in out:
self.log("[OK] 解压完成")
break
# 读取输出
try:
if stdout.channel.recv_ready():
chunk = stdout.channel.recv(8192).decode('utf-8', errors='ignore')
output_buffer += chunk
# 打印重要输出
current_time = time.time()
if current_time - last_log_time >= 5: # 每5秒打印一次日志
for line in chunk.split('\n'):
line = line.strip()
if line:
# 过滤关键信息
if any(kw in line for kw in [
'部署', '安装', '启动', '完成', '成功',
'失败', '错误', '容器', 'Docker', '服务',
'ERROR', 'WARN', 'INFO', '系统'
]):
self.log(f"[部署] {line}")
last_log_time = current_time
except Exception as e:
pass
# 每60秒输出进度
elapsed = int(time.time() - self.deploy_start_time)
if elapsed > 0 and elapsed % 60 == 0:
progress_time = time.time()
if progress_time - last_progress_time >= 55:
self.log(f"[进度] 部署进行中... 已用时: {int(elapsed/60)}分钟/{40}分钟")
last_progress_time = progress_time
self.check_container_status()
# 检查超时
if elapsed > 2700: # 45分钟超时
self.log("部署超时,终止监控", "WARN")
# 也检查进程
if pid and pid.isdigit():
code, out, err = self.exec_cmd(f"ps -p {pid} > /dev/null 2>&1 && echo 'running' || echo 'done'")
if 'done' in out and 'EXTRACT_DONE' not in out:
# 进程结束但没看到完成标志,可能解压完了
time.sleep(5)
code, out2, err = self.exec_cmd(f"ls {self.deploy_dir}/new_auto.sh 2>&1")
if 'new_auto.sh' in out2:
self.log("[OK] 解压完成(通过文件检查确认)")
break
time.sleep(2)
# 获取最终输出
try:
remaining_output = stdout.read().decode('utf-8', errors='ignore')
output_buffer += remaining_output
except:
pass
deploy_time = int((time.time() - self.deploy_start_time) / 60)
self.log("=" * 60)
self.log(f"部署脚本执行完成,用时: {deploy_time}分钟")
self.log("=" * 60)
return True
if waited >= max_wait:
self.log("[FAIL] 解压超时(20分钟)", "ERROR")
return False
except Exception as e:
self.log(f"执行部署脚本时出错: {str(e)}", "ERROR")
import traceback
traceback.print_exc()
# 确认解压结果
code, out, err = self.exec_cmd(f"ls {self.deploy_dir}/new_auto.sh 2>&1")
if 'new_auto.sh' not in out:
self.log("[FAIL] 解压后未找到部署脚本", "ERROR")
return False
self.log("[OK] 解压成功,部署脚本已就位")
def check_container_status(self):
"""检查容器状态"""
try:
stdin, stdout, stderr = self.ssh_client.exec_command(
"docker ps --format 'table {{.Names}}\t{{.Status}}' 2>/dev/null | head -20"
)
output = stdout.read().decode('utf-8', errors='ignore')
if output.strip():
lines = output.strip().split('\n')
count = len(lines) - 1 if len(lines) > 1 else 0
if count > 0:
self.log(f"[容器] 运行中: {count}个")
# 赋权
self.log("赋予脚本可执行权限...")
code, out, err = self.exec_cmd(f"cd {self.deploy_dir} && chmod 755 *.sh && ls -l *.sh | head -5")
self.log(f"脚本权限:\n{out}")
self.log("[OK] 脚本赋权完成")
return True
except Exception as e:
return False
def wait_for_services(self):
"""等待服务启动"""
def step4_run_deployment(self):
"""步骤4:运行 new_auto.sh --all(禁止中断)"""
self.log("=" * 60)
self.log("等待服务启动...")
self.log("【步骤4】运行部署脚本 new_auto.sh --all")
self.log("【重要】部署过程禁止中断!预计40分钟")
self.log("=" * 60)
max_wait = 600 # 10分钟
check_interval = 30
for i in range(0, max_wait, check_interval):
elapsed = i + check_interval
self.log(f"等待中... {elapsed}秒/{max_wait}秒")
# 检查预定对外服务日志
try:
log_path = "/data/services/api/java-meeting/java-meeting-extapi/logs/ubains-INFO-AND-ERROR.log"
stdin, stdout, stderr = self.ssh_client.exec_command(
f"tail -50 {log_path} 2>/dev/null | grep -i 'SYSTEMVERSION\\|target_api' || echo 'waiting'"
)
output = stdout.read().decode('utf-8', errors='ignore')
self.deploy_start_time = time.time()
if 'SYSTEMVERSION' in output and 'target_api' in output:
self.log("[OK] 预定对外服务已启动")
return True
except:
pass
# 清理旧的部署日志
self.exec_cmd(f"rm -f {self.deploy_log}")
time.sleep(check_interval)
# 写部署启动脚本到服务器,使用 yes y 自动确认可能的提示
launcher_script = f"""#!/bin/bash
cd {self.deploy_dir}
yes y | ./new_auto.sh --all
echo "DEPLOY_SCRIPT_FINISHED"
"""
self.exec_cmd(f"cat > /tmp/run_deploy.sh << 'DEPLOY_EOF'\n{launcher_script}\nDEPLOY_EOF")
self.exec_cmd("chmod +x /tmp/run_deploy.sh")
self.log("[WARN] 服务启动等待超时", "WARN")
# 使用独立通道后台启动,避免阻塞
self.log("启动部署脚本(后台运行)...")
output = self.exec_background(
f"nohup /tmp/run_deploy.sh </dev/null >{self.deploy_log} 2>&1 & echo $!"
)
pid = output.strip().split('\n')[-1].strip()
self.log(f"部署进程PID: {pid}")
# 等几秒确认进程已启动
time.sleep(5)
if pid and pid.isdigit():
code, out, err = self.exec_cmd(f"ps -p {pid} > /dev/null 2>&1 && echo 'running' || echo 'not_found'")
if 'not_found' in out:
self.log("[WARN] 进程PID已不存在,检查日志...", "WARN")
# 可能是 nohup 命令本身的PID,不是脚本的PID
# 查找实际的 new_auto.sh 进程
code, out, err = self.exec_cmd("pgrep -f 'new_auto.sh' | head -1")
actual_pid = out.strip()
if actual_pid and actual_pid.isdigit():
pid = actual_pid
self.log(f"找到实际部署进程PID: {pid}")
else:
# 检查日志文件
code, out, err = self.exec_cmd(f"cat {self.deploy_log} 2>/dev/null | head -20")
self.log(f"部署日志:\n{out}")
if not out.strip():
self.log("[FAIL] 部署进程未启动且无日志输出", "ERROR")
return False
def test_api_with_retry(self, url, expected_keyword, api_name, max_retries=5):
"""使用重试机制测试API"""
self.log(f"\n测试 {api_name}")
self.log(f"URL: {url}")
for retry in range(max_retries):
try:
response = requests.get(url, verify=False, timeout=30)
response_text = response.text
if not pid or not pid.isdigit():
# 尝试用 pgrep 查找
code, out, err = self.exec_cmd("pgrep -f 'new_auto.sh' | head -1")
pid = out.strip()
if pid and pid.isdigit():
self.log(f"通过pgrep找到部署进程: {pid}")
else:
# 检查日志是否有内容(可能脚本已经快速完成了或失败了)
time.sleep(10)
code, out, err = self.exec_cmd(f"wc -l {self.deploy_log} 2>/dev/null || echo '0'")
if '0' in out or not out.strip():
self.log("[FAIL] 无法找到部署进程且无日志", "ERROR")
return False
# 有日志输出,说明脚本已运行或正在运行
self.log("[WARN] 无法获取PID,但有日志输出,继续监控...", "WARN")
pid = None
# 监控部署进度
max_wait = 3600 # 60分钟超时
waited = 0
last_progress_minute = -1
while waited < max_wait:
time.sleep(15)
waited += 15
current_minute = int(waited / 60)
# 每分钟输出一次进度
if current_minute > last_progress_minute:
last_progress_minute = current_minute
# 读取日志大小
code, size_out, _ = self.exec_cmd(f"wc -l {self.deploy_log} 2>/dev/null || echo '0'")
log_lines = size_out.strip().split()[0] if size_out.strip() else '0'
# 读取最后几行关键信息
code, tail_out, _ = self.exec_cmd(
f"tail -30 {self.deploy_log} 2>/dev/null | grep -E "
f"'部署|安装|启动|完成|成功|失败|错误|ERROR|容器|Docker|服务|"
f"系统|middleware|database|redis|nginx|解压|loading|pull|image' | tail -5"
)
self.log(f"[进度] {current_minute}分钟/40分钟 | 日志行数: {log_lines}")
if tail_out.strip():
for line in tail_out.strip().split('\n')[-3:]:
if line.strip():
self.log(f" > {line.strip()}")
# 检查是否完成
code, out, err = self.exec_cmd(
f"grep 'DEPLOY_SCRIPT_FINISHED' {self.deploy_log} 2>/dev/null && echo 'FINISHED' || echo 'RUNNING'"
)
if 'FINISHED' in out:
self.log("[OK] 部署脚本执行完成")
break
# 检查是否包含预期关键词
if expected_keyword in response_text:
self.log(f"[OK] {api_name} 响应正常 (第{retry + 1}次尝试)")
return True
elif '<!DOCTYPE html>' in response_text and 'Error' in response_text:
self.log(f"[FAIL] {api_name} 返回错误页面 (第{retry + 1}次尝试)", "WARN")
# 也检查进程是否还在运行
if pid and pid.isdigit():
code, out, err = self.exec_cmd(f"ps -p {pid} > /dev/null 2>&1 && echo 'running' || echo 'done'")
if 'done' in out:
# 进程结束,再检查日志
time.sleep(5)
code, out, err = self.exec_cmd(
f"grep 'DEPLOY_SCRIPT_FINISHED' {self.deploy_log} 2>/dev/null && echo 'FINISHED' || echo 'NOT_FINISHED'"
)
if 'FINISHED' in out:
self.log("[OK] 部署脚本执行完成")
else:
# 进程结束但没有完成标志,检查日志尾部
code, out, err = self.exec_cmd(f"tail -30 {self.deploy_log}")
self.log(f"部署日志末尾:\n{out}")
if 'source /etc/profile' in out:
self.log("[OK] 检测到完成标志")
else:
self.log(f"[WARN] {api_name} 响应不符合预期 (第{retry + 1}次尝试)", "WARN")
self.log("[WARN] 进程已结束,但未检测到明确的完成标志", "WARN")
break
except Exception as e:
self.log(f"[WARN] {api_name} 请求失败 (第{retry + 1}次尝试): {str(e)}", "WARN")
else:
self.log("[FAIL] 部署超时(60分钟)", "ERROR")
return False
if retry < max_retries - 1:
self.log("等待30秒后重试...")
time.sleep(30)
# 执行 source /etc/profile
self.exec_cmd("source /etc/profile")
self.log(f"[FAIL] {api_name} 经过{max_retries}次尝试后仍然失败", "ERROR")
return False
deploy_time = int((time.time() - self.deploy_start_time) / 60)
self.log(f"部署脚本执行完成,用时: {deploy_time}分钟")
return True
def perform_acceptance_check(self):
"""执行验收检查"""
def step5_acceptance_check(self):
"""步骤5:验收检查"""
self.log("=" * 60)
self.log("开始验收检查")
self.log("【步骤5】验收检查")
self.log("=" * 60)
results = {}
# 1. 检查容器状态
self.log("\n1. 检查容器状态...")
try:
stdin, stdout, stderr = self.ssh_client.exec_command(
"docker ps --format 'table {{.Names}}\t{{.Status}}'"
)
docker_output = stdout.read().decode('utf-8', errors='ignore')
self.log(f"\n容器状态:\n{docker_output}")
container_count = len([l for l in docker_output.split('\n') if l.strip() and 'NAMES' not in l])
# 5.1 检查容器状态
self.log("\n--- 5.1 检查容器状态 ---")
code, out, err = self.exec_cmd("docker ps --format 'table {{.Names}}\t{{.Status}}'")
self.log(f"容器状态:\n{out}")
container_lines = [l for l in out.split('\n') if l.strip() and 'NAMES' not in l]
container_count = len(container_lines)
results['容器状态'] = container_count >= 5
self.log(f"运行中的容器: {container_count}个")
except Exception as e:
self.log(f"检查容器失败: {str(e)}", "ERROR")
results['容器状态'] = False
self.log(f"运行中的容器: {container_count}个 -> {'通过' if results['容器状态'] else '不足'}")
# 2. 检查服务日志
self.log("\n2. 检查服务日志...")
log_checks = {
"预定对外服务": "/data/services/api/java-meeting/java-meeting-extapi/logs/ubains-INFO-AND-ERROR.log"
}
# 5.2 等待服务启动并检查日志
self.log("\n--- 5.2 等待服务启动 ---")
results['服务日志'] = self._wait_for_service_log()
for service_name, log_path in log_checks.items():
try:
stdin, stdout, stderr = self.ssh_client.exec_command(
f"tail -100 {log_path} 2>/dev/null | grep 'SYSTEMVERSION' || echo 'not found'"
)
output = stdout.read().decode('utf-8', errors='ignore')
if 'SYSTEMVERSION' in output and 'target_api' in output:
self.log(f"[OK] {service_name} 日志正常")
results[f'{service_name}_日志'] = True
else:
self.log(f"[WARN] {service_name} 日志未找到版本信息", "WARN")
results[f'{service_name}_日志'] = False
except Exception as e:
self.log(f"[WARN] 检查{service_name}日志失败: {str(e)}", "WARN")
results[f'{service_name}_日志'] = False
# 5.3 检查服务日志异常
self.log("\n--- 5.3 检查服务日志异常 ---")
error_summary = self._check_service_errors()
# 3. 检查接口状态
self.log("\n3. 检查接口状态...")
# 5.4 接口测试
self.log("\n--- 5.4 接口测试(重试:5次,间隔30秒) ---")
base_url = f"https://{self.host}"
results['预定对外接口'] = self.test_api_with_retry(
results['预定对外接口'] = self._test_api_with_retry(
f"{base_url}/exapi/message/getMsgPageList",
"无效token",
"预定对外服务接口"
"无效token", "预定对外服务接口"
)
results['预定系统接口'] = self.test_api_with_retry(
results['预定系统接口'] = self._test_api_with_retry(
f"{base_url}/meetingV3/api/systemConfiguration/globalConfig?companyNumber=CN-SZ-00-0201",
"accessToken",
"预定系统接口"
"accessToken", "预定系统接口"
)
results['运维集控接口'] = self.test_api_with_retry(
results['运维集控接口'] = self._test_api_with_retry(
f"{base_url}/monitor/api2/api/servermonitor/",
"用户不存在",
"运维集控系统接口"
"用户不存在", "运维集控系统接口"
)
results['讯飞转录接口'] = self.test_api_with_retry(
results['讯飞转录接口'] = self._test_api_with_retry(
f"{base_url}/voice/api/iflytek/roommaster?company_id=1&user_id=8&company_secret=57d00f9f-020f-5f1f-b788-55fae843bceb&getall=1",
"缺少关键参数",
"讯飞转录系统接口"
"缺少关键参数", "讯飞转录系统接口"
)
return results
return results, error_summary
def _wait_for_service_log(self):
"""等待服务日志输出版本信息"""
log_path = "/data/services/api/java-meeting/java-meeting-extapi/logs/ubains-INFO-AND-ERROR.log"
for phase, max_wait in [("首次", 600), ("二次", 600)]:
self.log(f" {phase}等待(最多{max_wait // 60}分钟)...")
for waited in range(0, max_wait, 30):
self.log(f" 等待中... {waited + 30}秒/{max_wait}秒")
code, out, err = self.exec_cmd(
f"tail -50 {log_path} 2>/dev/null | grep -i 'SYSTEMVERSION\\|target_api' || echo 'waiting'"
)
if 'SYSTEMVERSION' in out and 'target_api' in out:
self.log(f"[OK] 预定对外服务已启动({phase}等待)")
return True
time.sleep(30)
def check_service_logs_for_errors(self):
"""检查服务日志是否有异常"""
self.log("\n检查服务日志中的异常...")
self.log("[FAIL] 服务启动等待超时", "ERROR")
return False
def _check_service_errors(self):
"""检查四个服务的日志异常"""
log_paths = {
"预定对外服务": "/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",
......@@ -404,36 +457,67 @@ class X86AutoDeploy:
}
error_summary = {}
for service_name, log_path in log_paths.items():
try:
stdin, stdout, stderr = self.ssh_client.exec_command(
f"tail -100 {log_path} 2>/dev/null | grep -i 'error\\|exception' || echo 'clean'"
for name, path in log_paths.items():
code, out, err = self.exec_cmd(
f"tail -100 {path} 2>/dev/null | grep -i 'error\\|exception' || echo 'clean'"
)
output = stdout.read().decode('utf-8', errors='ignore')
if output.strip() and output.strip() != 'clean':
error_count = len([l for l in output.split('\n') if l.strip()])
error_summary[service_name] = error_count
self.log(f"[WARN] {service_name} 发现 {error_count} 条异常记录", "WARN")
if out.strip() and out.strip() != 'clean':
count = len([l for l in out.split('\n') if l.strip()])
error_summary[name] = count
self.log(f"[WARN] {name}: 发现 {count} 条异常记录", "WARN")
else:
self.log(f"[OK] {service_name} 日志无明显异常")
error_summary[service_name] = 0
error_summary[name] = 0
self.log(f"[OK] {name}: 无明显异常")
return error_summary
def _test_api_with_retry(self, url, keyword, name, max_retries=5):
"""接口测试:5次重试,间隔30秒,成功即停"""
self.log(f"\n 测试 {name}")
self.log(f" URL: {url}")
for retry in range(max_retries):
try:
resp = requests.get(url, verify=False, timeout=30)
if keyword in resp.text:
self.log(f" [OK] {name} 正常 (第{retry + 1}次)")
# 成功后等30秒再确认一次
if retry < max_retries - 1:
time.sleep(30)
resp2 = requests.get(url, verify=False, timeout=30)
if keyword in resp2.text:
self.log(f" [OK] {name} 二次确认正常")
return True
else:
self.log(f" [FAIL] {name} 响应异常 (第{retry + 1}次)", "WARN")
except Exception as e:
self.log(f"[WARN] 无法读取 {service_name} 日志: {str(e)}", "WARN")
error_summary[service_name] = -1
self.log(f" [FAIL] {name} 请求失败 (第{retry + 1}次): {str(e)}", "WARN")
return error_summary
if retry < max_retries - 1:
self.log(" 等待30秒后重试...")
time.sleep(30)
def generate_report(self, results, error_summary):
"""生成部署报告"""
self.log("\n" + "=" * 60)
self.log("部署验收报告")
self.log(f" [FAIL] {name} 经{max_retries}次尝试后仍然失败", "ERROR")
return False
def step6_authorization(self):
"""步骤6:系统授权指导"""
self.log("=" * 60)
self.log("【步骤6】系统授权")
self.log("需要通过浏览器Web界面操作")
self.log("=" * 60)
self.log("请手动执行以下步骤:")
self.log(f" 1. 访问: https://{self.host}/#/LoginConfig")
self.log(f" 2. 登录: {self.admin_user} / {self.admin_pass}")
self.log(" 3. 验证码: csba")
self.log(f" 4. 上传授权文件: {self.license_path}")
self.log(" 5. 勾选 运维系统、预定系统2.0、预定系统3.0 -> 重启已选服务")
self.log(" 6. 填写项目信息 -> 保存")
return True
def generate_report(self, results, error_summary):
"""生成部署验收报告"""
total_time = int((time.time() - self.total_start_time) / 60)
deploy_time = int((self.deploy_start_time - self.total_start_time) / 60) if self.deploy_start_time else 0
deploy_time = int((time.time() - self.deploy_start_time) / 60) if self.deploy_start_time else 0
report_lines = [
"# 远程自动化部署报告",
......@@ -446,13 +530,10 @@ class X86AutoDeploy:
]
for key, value in results.items():
status = "✓ 通过" if value else "✗ 失败"
report_lines.append(f"- {status}: {key}")
report_lines.extend([
"\n### 2. 日志异常检查",
])
status = "通过" if value else "失败"
report_lines.append(f"- [{status}] {key}")
report_lines.append("\n### 2. 日志异常检查")
for service, count in error_summary.items():
if count > 0:
report_lines.append(f"- [!] {service}: {count} 条异常记录")
......@@ -461,7 +542,6 @@ class X86AutoDeploy:
else:
report_lines.append(f"- [?] {service}: 无法检查")
# 计算通过率
passed = sum(1 for v in results.values() if v)
total = len(results)
pass_rate = (passed / total * 100) if total > 0 else 0
......@@ -473,31 +553,23 @@ class X86AutoDeploy:
])
if pass_rate >= 80:
report_lines.extend([
"\n**结论**: 部署验收基本通过",
"\n## 二、后续步骤",
"\n### 1. 系统授权",
f"- 访问: https://{self.host}/#/LoginConfig",
"- 账号: superadmin / Ubains@1357",
"- 验证码: csba",
"- 上传授权文件",
"\n### 2. 重启服务",
"- 勾选需要重启的服务",
"- 点击【重启已选服务】",
"\n### 3. 创建管理员(暂时跳过)",
"- 根据部署文档第四章操作",
])
report_lines.append("\n**结论**: 部署验收基本通过")
else:
report_lines.append("\n**结论**: 部署存在问题,需要检查失败项")
report_lines.extend([
"\n**结论**: 部署存在问题,需要检查失败项",
"\n## 二、问题处理",
"\n请检查上述失败项目,必要时联系技术支持。",
"\n## 二、后续步骤",
f"1. 系统授权: https://{self.host}/#/LoginConfig",
f" - 账号: {self.admin_user} / {self.admin_pass}",
" - 验证码: csba",
f" - 授权文件: {self.license_path}",
"2. 重启服务后再次验证接口",
"3. 创建管理员(暂时跳过)",
])
report = '\n'.join(report_lines)
# 保存报告
reports_dir = os.path.join(os.path.dirname(__file__), 'reports')
reports_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'reports')
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
report_file = os.path.join(reports_dir, f'{self.host}_deployment_report_{timestamp}.md')
......@@ -508,63 +580,53 @@ class X86AutoDeploy:
except Exception as e:
self.log(f"保存报告失败: {str(e)}", "ERROR")
# 打印报告
print("\n" + report)
self.log("\n" + report)
return report_file
def close(self):
"""关闭连接"""
"""关闭SSH连接"""
if self.ssh_client:
self.ssh_client.close()
self.log("SSH连接已关闭")
def main():
print("=" * 80)
print("X86服务器远程自动化部署")
print("目标服务器: 192.168.5.52")
print("部署脚本: new_auto.sh --all")
print("=" * 80)
print()
deploy = X86AutoDeploy()
deploy.init_log_file()
deploy.total_start_time = time.time()
deploy.log("=" * 60)
deploy.log("X86服务器远程自动化部署")
deploy.log(f"目标服务器: 192.168.5.52")
deploy.log("部署脚本: new_auto.sh --all")
deploy.log("严格按照部署文档执行,禁止中断解压缩操作")
deploy.log("=" * 60)
try:
# 1. 连接SSH
if not deploy.connect_ssh():
return 1
# 2. 检查前置条件
if not deploy.check_prerequisites():
deploy.log("前置条件检查失败,但继续执行部署", "WARN")
# 3. 清理现有进程
deploy.cleanup_existing_processes()
if not deploy.step1_check_disk():
deploy.log("硬盘检查失败", "WARN")
# 4. 执行部署脚本
if not deploy.execute_deployment():
deploy.log("部署脚本执行失败", "ERROR")
if not deploy.step2_verify_package():
deploy.log("部署包校验失败", "ERROR")
deploy.close()
return 1
# 5. 等待服务启动
deploy.wait_for_services()
# 6. 验收检查
results = deploy.perform_acceptance_check()
if not deploy.step3_extract_and_chmod():
deploy.log("解压或赋权失败", "ERROR")
deploy.close()
return 1
# 7. 检查日志异常
error_summary = deploy.check_service_logs_for_errors()
if not deploy.step4_run_deployment():
deploy.log("部署脚本执行失败", "ERROR")
# 8. 生成报告
results, error_summary = deploy.step5_acceptance_check()
deploy.step6_authorization()
deploy.generate_report(results, error_summary)
deploy.close()
# 判断是否成功
if all(results.values()):
deploy.log("\n[SUCCESS] 部署验收通过!")
return 0
......@@ -573,9 +635,12 @@ def main():
return 1
except Exception as e:
deploy.log(f"部署过程出错: {str(e)}", "ERROR")
deploy.log(f"部署过程异常: {str(e)}", "ERROR")
try:
import traceback
traceback.print_exc()
except Exception:
pass
deploy.close()
return 1
......
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
X86服务器自动化部署脚本 - 使用 new_auto.sh --all 参数
严格按照需求文档执行部署操作
"""
import sys
import os
import time
import subprocess
import paramiko
import requests
from datetime import datetime
from urllib3.exceptions import InsecureRequestWarning
# 禁用SSL警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
class X86Deployment:
def __init__(self):
self.host = '192.168.5.52'
self.username = 'root'
self.password = 'Ubains@123'
self.deploy_dir = '/data/offline_auto_unifiedPlatform'
self.ssh_client = None
self.start_time = None
def log(self, message, level="INFO"):
"""输出日志"""
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(f"[{timestamp}] [{level}] {message}")
def connect_ssh(self):
"""连接SSH"""
self.log("正在连接SSH服务器...")
try:
self.ssh_client = paramiko.SSHClient()
self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.ssh_client.connect(self.host, username=self.username, password=self.password, timeout=30)
self.log("SSH连接成功")
return True
except Exception as e:
self.log(f"SSH连接失败: {str(e)}", "ERROR")
return False
def check_and_cleanup(self):
"""检查并清理现有部署进程"""
self.log("检查并清理现有部署进程...")
try:
# 终止可能存在的new_auto.sh进程
stdin, stdout, stderr = self.ssh_client.exec_command(
"pkill -9 -f new_auto.sh; sleep 2; echo '清理完成'"
)
stdout.read()
self.log("现有进程清理完成")
time.sleep(2)
return True
except Exception as e:
self.log(f"清理进程时出错: {str(e)}", "WARN")
return True
def run_deployment_script(self):
"""执行部署脚本 new_auto.sh --all"""
self.log("=" * 60)
self.log("开始执行部署脚本: new_auto.sh --all")
self.log("=" * 60)
self.start_time = time.time()
try:
# 切换到部署目录并执行脚本
cmd = f"cd {self.deploy_dir} && ./new_auto.sh --all"
self.log(f"执行命令: {cmd}")
self.log("预计部署时间: 40分钟")
# 使用exec_command执行,设置超时
stdin, stdout, stderr = self.ssh_client.exec_command(cmd, get_pty=True)
# 监控部署过程
output_buffer = ""
last_progress_time = time.time()
while True:
# 检查进程状态
if stdout.channel.exit_status_ready():
# 进程已结束
exit_code = stdout.channel.exit_status
self.log(f"部署脚本进程已结束,退出码: {exit_code}")
break
# 读取输出
try:
if stdout.channel.recv_ready():
chunk = stdout.channel.recv(4096).decode('utf-8', errors='ignore')
output_buffer += chunk
# 打印重要输出
if any(keyword in chunk for keyword in ['部署', '安装', '启动', '完成', '成功', '失败', '错误', 'error']):
# 清理并打印
for line in chunk.split('\n'):
line = line.strip()
if line and any(kw in line for kw in ['部署', '安装', '启动', '完成', '成功', '失败', '错误']):
self.log(f"[部署输出] {line}")
except Exception as e:
pass
# 每60秒输出进度
elapsed = int(time.time() - self.start_time)
if elapsed % 60 == 0 and elapsed > 0:
progress_time = time.time()
if progress_time - last_progress_time >= 55: # 避免重复输出
self.log(f"[进度] 部署进行中... 已用时: {int(elapsed/60)}分钟")
last_progress_time = progress_time
# 检查容器状态
self.check_container_status()
# 检查是否超时
if elapsed > 2700: # 45分钟超时
self.log("部署超时", "WARN")
break
time.sleep(5)
# 获取最终输出
remaining_output = stdout.read().decode('utf-8', errors='ignore')
output_buffer += remaining_output
self.log("=" * 60)
self.log("部署脚本执行完成")
self.log("=" * 60)
return True
except Exception as e:
self.log(f"执行部署脚本时出错: {str(e)}", "ERROR")
return False
def check_container_status(self):
"""检查容器状态"""
try:
stdin, stdout, stderr = self.ssh_client.exec_command(
"docker ps --format '{{.Names}}' | wc -l"
)
count = int(stdout.read().decode().strip())
if count > 0:
self.log(f"[容器状态] 运行中的容器数量: {count}")
return count
except:
return 0
def check_deployment_result(self):
"""检查部署结果"""
self.log("=" * 60)
self.log("开始检查部署结果")
self.log("=" * 60)
results = {
'containers': False,
'logs': False,
'external_api': False,
'meeting_api': False,
'monitor_api': False,
'voice_api': False
}
# 1. 检查容器状态
self.log("1. 检查容器状态...")
try:
stdin, stdout, stderr = self.ssh_client.exec_command(
"docker ps --format 'table {{.Names}}\t{{.Status}}'"
)
docker_output = stdout.read().decode('utf-8', errors='ignore')
self.log(f"\n容器状态:\n{docker_output}")
container_count = docker_output.count('\n') - 1 # 减去表头
if container_count >= 5:
self.log(f"[OK] 运行中的容器数量: {container_count}")
results['containers'] = True
else:
self.log(f"[FAIL] 容器数量不足: {container_count}", "ERROR")
except Exception as e:
self.log(f"检查容器状态失败: {str(e)}", "ERROR")
# 2. 检查预定对外服务日志
self.log("\n2. 检查预定对外服务日志...")
log_path = "/data/services/api/java-meeting/java-meeting-extapi/logs/ubains-INFO-AND-ERROR.log"
# 等待日志输出
max_wait = 600 # 10分钟
wait_start = time.time()
while time.time() - wait_start < max_wait:
try:
stdin, stdout, stderr = self.ssh_client.exec_command(
f"tail -100 {log_path} | grep 'SYSTEMVERSION'"
)
log_output = stdout.read().decode('utf-8', errors='ignore')
if 'SYSTEMVERSION' in log_output and 'target_api_integration' in log_output:
self.log(f"[OK] 找到版本信息: {log_output.strip()}")
results['logs'] = True
break
else:
self.log("等待服务启动...")
time.sleep(30)
except Exception as e:
self.log(f"检查日志失败: {str(e)}", "WARN")
time.sleep(30)
else:
self.log("[FAIL] 10分钟后仍未检测到服务启动", "ERROR")
# 3. 使用重试机制检查接口状态
self.log("\n3. 检查接口状态(使用重试机制)...")
# 对外接口
results['external_api'] = self.test_api_with_retry(
"https://192.168.5.52/exapi/message/getMsgPageList",
"无效token",
"预定对外服务接口"
)
# 预定系统接口
results['meeting_api'] = self.test_api_with_retry(
"https://192.168.5.52/meetingV3/api/systemConfiguration/globalConfig?companyNumber=CN-SZ-00-0201",
"accessToken",
"预定系统接口"
)
# 运维集控系统接口
results['monitor_api'] = self.test_api_with_retry(
"https://192.168.5.52/monitor/api2/api/servermonitor/",
"用户不存在",
"运维集控系统接口"
)
# 讯飞转录系统接口
results['voice_api'] = self.test_api_with_retry(
"https://192.168.5.52/voice/api/iflytek/roommaster?company_id=1&user_id=8&company_secret=57d00f9f-020f-5f1f-b788-55fae843bceb&getall=1",
"缺少关键参数",
"讯飞转录系统接口"
)
# 输出结果摘要
self.log("=" * 60)
self.log("部署检查结果摘要")
self.log("=" * 60)
total_time = int((time.time() - self.start_time) / 60)
self.log(f"总用时: {total_time} 分钟")
for key, value in results.items():
status = "[OK]" if value else "[FAIL]"
self.log(f"{status} {key}")
all_ok = all(results.values())
if all_ok:
self.log("\n[SUCCESS] 部署验收通过!")
else:
self.log("\n[WARN] 部署存在问题,请检查上述失败项")
return all_ok
def test_api_with_retry(self, url, expected_keyword, api_name):
"""使用重试机制测试API"""
self.log(f"\n测试 {api_name}: {url}")
retry_count = 0
max_retries = 5
while retry_count < max_retries:
try:
response = requests.get(url, verify=False, timeout=30)
response_text = response.text
# 检查是否包含预期关键词
if expected_keyword in response_text:
self.log(f"[OK] {api_name} 响应正常 (尝试 {retry_count + 1}/{max_retries})")
return True
elif '<!DOCTYPE html>' in response_text and 'Error' in response_text:
self.log(f"[FAIL] {api_name} 返回错误页面 (尝试 {retry_count + 1}/{max_retries})")
else:
self.log(f"[WARN] {api_name} 响应不符合预期 (尝试 {retry_count + 1}/{max_retries})")
self.log(f"响应内容: {response_text[:200]}")
except Exception as e:
self.log(f"[WARN] {api_name} 请求失败 (尝试 {retry_count + 1}/{max_retries}): {str(e)}")
retry_count += 1
if retry_count < max_retries:
self.log("等待30秒后重试...")
time.sleep(30)
self.log(f"[FAIL] {api_name} 经过 {max_retries} 次尝试后仍然失败", "ERROR")
return False
def check_service_logs(self):
"""检查服务日志是否有异常"""
self.log("\n检查服务日志...")
log_paths = {
"预定对外服务": "/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 service_name, log_path in log_paths.items():
try:
stdin, stdout, stderr = self.ssh_client.exec_command(
f"tail -50 {log_path} 2>/dev/null || echo '日志文件不存在'"
)
log_output = stdout.read().decode('utf-8', errors='ignore')
if 'ERROR' in log_output.upper() or 'EXCEPTION' in log_output.upper():
self.log(f"[WARN] {service_name} 日志中发现异常:", "WARN")
else:
self.log(f"[OK] {service_name} 日志正常")
except Exception as e:
self.log(f"[WARN] 无法读取 {service_name} 日志: {str(e)}", "WARN")
def close(self):
"""关闭连接"""
if self.ssh_client:
self.ssh_client.close()
self.log("SSH连接已关闭")
def main():
print("=" * 80)
print("X86服务器远程自动化部署")
print("目标服务器: 192.168.5.52")
print("部署脚本: new_auto.sh --all")
print("=" * 80)
print()
deploy = X86Deployment()
try:
# 1. 连接SSH
if not deploy.connect_ssh():
return 1
# 2. 清理现有进程
deploy.check_and_cleanup()
# 3. 执行部署脚本
if not deploy.run_deployment_script():
return 1
# 4. 等待服务启动
deploy.log("\n等待服务启动...")
time.sleep(60)
# 5. 检查部署结果
success = deploy.check_deployment_result()
# 6. 检查服务日志
deploy.check_service_logs()
# 7. 输出后续步骤
print("\n" + "=" * 80)
print("部署脚本执行完成")
print("=" * 80)
print("\n后续步骤:")
print("1. 系统授权: https://192.168.5.52/#/LoginConfig")
print(" 账号: superadmin / Ubains@1357")
print(" 验证码: csba")
print(" 授权文件: \\\\192.168.9.9\\发布版本\\03服务器部署\\临时使用-新统一平台\\测试授权文件-请勿使用\\5.52授权文件\\license.zip")
print("\n2. 创建管理员: 为'自动化'公司创建admin用户")
print("\n3. 前台访问: https://192.168.5.52/")
print(" 后台访问: https://192.168.5.52/#/LoginAdmin")
deploy.close()
return 0 if success else 1
except Exception as e:
deploy.log(f"部署过程出错: {str(e)}", "ERROR")
import traceback
traceback.print_exc()
deploy.close()
return 1
if __name__ == '__main__':
sys.exit(main())
......@@ -60,7 +60,7 @@
## 验收要求
1. 自动化部署完成后检查容器状态是否正常,核查容器日志是否正确。
2. 检查对外服务状态:
- 等待10分钟后执行接口调用:
- 日志是否正确打印如下信息`SYSTEMVERSION :: target_api_integration2.0.2612.258 2026-03-17 10:59:54`,版本号不固定判断,只要有就行,如有则标识为服务启动正常,若无则再等待10分钟,再次检查,若10分钟后仍然未输出,则标识为启动异常,记录异常日志。
- 调用对外接口`curl -k https://服务器IP/exapi/message/getMsgPageList`
- 成功:返回信息:`{"success":false,"code":"A0076","message":"无效token","result":"Full authentication is required to access this resource"}`
- 失败:返回信息:
......@@ -91,7 +91,6 @@
- 按照部署文档中第三章系统授权进行执行操作,如遇验证码输入则填入`csba`
- 需上传的授权文件路径根据服务器IP获取对应的授权文件,文档顶部有标注对应路径。
- 继续根据文档执行第三章节的授权操作。
4. 新统一平台服务检查
- 检查服务启动状态:
- 检查预定对内、对外服务日志是否正常,是否存在异常日志输出。
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论