This commit is contained in:
1
2026-01-22 16:01:52 +00:00
parent 3af709f633
commit 7d8497250d
9 changed files with 143 additions and 163 deletions

View File

@@ -149,7 +149,6 @@ func (s *ServerHandler) executeScript(scriptContent, scriptName string) (string,
}
}
// 执行完整的自动化部署流程
func (s *ServerHandler) executeFullDeployment() error {
s.sendTerminalOutput(s.session.WebSocket, "开始执行完整自动化部署流程...")
@@ -164,6 +163,9 @@ func (s *ServerHandler) executeFullDeployment() error {
remoteExePath := fmt.Sprintf("%s/%s", defaultWorkDir, randomFileName)
onlineID := fmt.Sprintf("%d", s.ServerList.OnlineID)
// 固定Screen会话名称为logic
const fixedScreenSession = "logic"
// 创建完整的部署脚本(不包含#!/bin/bash
deploymentScript := fmt.Sprintf(`
@@ -188,7 +190,7 @@ else
echo "检测到dnf正在安装screen..."
dnf install -y screen > /dev/null 2>&1
elif command -v pacman &> /dev/null; then
echo "检测到pacman正在安装screen..."
echo "=== 检测到pacman正在安装screen ==="
pacman -S --noconfirm screen > /dev/null 2>&1
else
echo "=== 不支持的系统包管理器无法自动安装Screen ==="
@@ -203,28 +205,50 @@ else
fi
fi
# ===== 停止旧Screen会话 =====
if [ -n "%s" ] && [ "%s" != "" ]; then
echo "检查并停止旧会话: %s"
if screen -ls | grep -q "%s"; then
echo "发现旧会话,正在停止: %s"
screen -S %s -X quit 2>/dev/null || true
#pkill -f "%s" 2>/dev/null || true
# 可选:等待几秒,确认会话是否退出(仅提示,不强制)
sleep 5
# 检查会话是否仍存在(仅告知状态,不做强制操作)
if screen -ls | grep -q "$SESSION_NAME"; then
echo "⚠️ 警告:旧会话未退出(进程可能正在执行清理逻辑),未执行强制杀死,请手动确认"
else
echo "=== 旧会话优雅停止成功 ==="
fi
echo "=== 旧会话已停止 ==="
else
echo "=== 旧会话不存在,无需停止 ==="
fi
# ===== 核心逻辑给logic会话发exit命令 + 循环等待Screen主进程退出 =====
echo "开始处理固定名称[logic]的Screen会话..."
SCREEN_PID=""
# 1. 先查找logic会话是否存在并提取主PID
if screen -ls "%s" | grep -q "%s"; then
echo "找到[logic]会话提取主PID..."
SCREEN_PID=$(screen -ls "%s" | grep -oE '[0-9]+\.'"$1" | cut -d. -f1)
# 2. 给Screen会话发送exit命令核心操作
echo "给[logic]会话发送exit命令触发会话退出..."
screen -x -S "%s" -p 0 -X stuff "exit\n" 2>/dev/null || true
else
echo "无旧Screen会话跳过停止"
echo "=== 未找到名称为[logic]的Screen会话跳过终止 ==="
fi
# 3. 循环等待Screen主进程退出核心等Screen本身退出
if [ -n "$SCREEN_PID" ] && [ "$SCREEN_PID" != "" ]; then
echo "开始循环等待[logic]会话主PID[$SCREEN_PID]退出..."
WAIT_COUNT=0
MAX_WAIT_SECONDS=30 # 最大等待30秒避免无限循环
while ps -p "$SCREEN_PID" > /dev/null 2>&1; do
sleep 0.5 # 每0.5秒检测一次Screen主进程状态
WAIT_COUNT=$((WAIT_COUNT + 1))
# 每2秒输出一次等待状态可选方便排查
if [ $((WAIT_COUNT % 4)) -eq 0 ]; then
echo "等待中...已等待$((WAIT_COUNT/2))秒(最大$MAX_WAIT_SECONDS秒"
fi
# 超过最大等待时间则退出循环,避免卡死
if [ $WAIT_COUNT -ge $((MAX_WAIT_SECONDS * 2)) ]; then
echo "⚠️ 等待超时($MAX_WAIT_SECONDS秒[logic]会话主PID[$SCREEN_PID]仍未退出"
# 兜底超时后给Screen主进程发kill 15
kill -15 "$SCREEN_PID" 2>/dev/null || true
break
fi
done
# 4. 检查Screen主进程最终状态
if ps -p "$SCREEN_PID" > /dev/null 2>&1; then
echo "❌ [logic]会话主PID[$SCREEN_PID]未退出,建议手动处理"
else
echo "✅ [logic]会话主PID[$SCREEN_PID]已成功退出"
fi
fi
# ===== 下载程序 =====
@@ -268,38 +292,36 @@ if [ $? -ne 0 ]; then
fi
echo "=== 权限设置完成 ==="
# 启动Screen会话
echo "正在启动Screen会话: %s"
screen -dmS "%s" bash -c '"%s" -id=%s | tee -a "$HOME/run.log"'
# 启动新程序到固定名称[logic]的Screen会话(重建会话)
echo "正在启动Screen会话: logic"
screen -dmS "logic" bash -c '"%s" -id=%s | tee -a "$HOME/run.log"'
# 等待一段时间确保会话启动
sleep 5
# 等待2秒确保会话启动
sleep 2
# 检查会话是否存在
if screen -ls | grep -q "%s"; then
echo "=== 程序启动成功Screen会话已创建 ==="
echo "=== 会话名称:%s ==="
# 检查logic会话是否启动成功
if screen -ls | grep -q "logic"; then
echo "=== 程序启动成功Screen会话[logic]已创建 ==="
echo "=== 会话名称:logic ==="
screen -ls
echo "程序已在后台Screen会话中运行"
echo "程序已在后台Screen会话[logic]中运行"
else
echo "=== 程序启动失败Screen会话未创建 ==="
echo "=== 程序启动失败Screen会话[logic]未创建 ==="
screen -ls
exit 1
fi
echo "#SCRIPT_EXECUTION_COMPLETE#"
`,
s.ServerList.OldScreen, s.ServerList.OldScreen, s.ServerList.OldScreen,
s.ServerList.OldScreen, s.ServerList.OldScreen, s.ServerList.OldScreen,
s.ServerList.OldScreen,
remoteExePath,
remoteExePath, remoteExePath,
remoteExePath, fileURL,
remoteExePath, fileURL,
remoteExePath, remoteExePath, remoteExePath,
remoteExePath,
randomFileName, randomFileName, remoteExePath, onlineID,
randomFileName, randomFileName)
fixedScreenSession, fixedScreenSession, fixedScreenSession, fixedScreenSession, // logic会话参数
remoteExePath, // 下载路径
remoteExePath, remoteExePath, // 删除旧文件
remoteExePath, fileURL, // wget下载
remoteExePath, fileURL, // curl下载
remoteExePath, remoteExePath, remoteExePath, // 文件验证
remoteExePath, // 执行权限
remoteExePath, onlineID, // 启动logic会话
)
// 执行完整的部署脚本
_, err := s.executeScript(deploymentScript, "full_deployment_"+grand.S(10))
@@ -307,8 +329,8 @@ echo "#SCRIPT_EXECUTION_COMPLETE#"
return err
}
// 保存会话名称
config.NewServerService().SetServerScreen(s.ServerList.OnlineID, randomFileName)
// 保存固定的logic会话名称
config.NewServerService().SetServerScreen(s.ServerList.OnlineID, fixedScreenSession)
s.sendTerminalOutput(s.session.WebSocket, "自动化部署完成")