```
refactor(common/cool/coolconfig): 修改RPC配置字段类型 将RPC字段从uint16类型更改为string类型的Address字段, 以支持更灵活的地址配置。同时更新了配置初始化逻辑, 从server.rpc改为server.address作为配置键。 ```
This commit is contained in:
@@ -198,145 +198,91 @@ else
|
||||
fi
|
||||
|
||||
#!/bin/bash
|
||||
# ===== 优雅终止logic会话(解决screen -ls卡住问题)=====
|
||||
echo "===== 优雅终止logic会话 ====="
|
||||
# 替换为你实际的screen名称(示例:logic)
|
||||
SCREEN_NAME="logic"
|
||||
LOG_FILE="./screen_logic_exit.log"
|
||||
# 核心:无任何可能阻塞的命令,全程实时输出,100%不卡住 + 彻底清理所有logic会话
|
||||
set -euo pipefail
|
||||
|
||||
# 调试开关(如需详细日志,取消set -x注释)
|
||||
set -o pipefail
|
||||
export PS4='[DEBUG] ${BASH_SOURCE}:${LINENO} - ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
|
||||
# set -x
|
||||
# ===== 仅需配置这1个变量 =====
|
||||
SCREEN_NAME="logic"
|
||||
|
||||
# ========== 核心函数(保留你的原版) ==========
|
||||
wait_for_process_exit() {
|
||||
local pidKilled=$1
|
||||
local begin=$(date +%s)
|
||||
local end
|
||||
local timeout=60
|
||||
|
||||
while kill -0 $pidKilled > /dev/null 2>&1; do
|
||||
echo -n "."
|
||||
sleep 1;
|
||||
|
||||
end=$(date +%s)
|
||||
if [ $((end - begin)) -gt $timeout ]; then
|
||||
echo -e "\n⚠️ 等待进程$pidKilled退出超时(已等${timeout}秒)"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
|
||||
if ! kill -0 $pidKilled > /dev/null 2>&1; then
|
||||
echo -e "\n✅ 进程$pidKilled已退出"
|
||||
# ===== 颜色输出函数(确保能看到输出)=====
|
||||
red() { echo -e "\033[31m[$(date +%H:%M:%S)] $1\033[0m"; }
|
||||
green() { echo -e "\033[32m[$(date +%H:%M:%S)] $1\033[0m"; }
|
||||
yellow() { echo -e "\033[33m[$(date +%H:%M:%S)] $1\033[0m"; }
|
||||
|
||||
# ===== 新增:彻底清理screen会话(核心修复)=====
|
||||
clean_screen_sessions() {
|
||||
local sess_id=$1
|
||||
# 1. 先优雅关闭screen会话
|
||||
screen -S "${sess_id}" -X quit >/dev/null 2>&1 || true
|
||||
sleep 0.3
|
||||
# 2. 提取会话PID并强制杀死
|
||||
local sess_pid=$(echo "${sess_id}" | cut -d. -f1)
|
||||
if [ -n "${sess_pid}" ]; then
|
||||
kill -9 "${sess_pid}" >/dev/null 2>&1 || true
|
||||
# 3. 杀死该PID的所有子进程
|
||||
pkill -9 -P "${sess_pid}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
pid_is_alive() {
|
||||
local pid=$1
|
||||
if [ -n "$pid" ] && kill -0 "$pid" > /dev/null 2>&1; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
# ===== 强制关闭所有阻塞的后台进程(先清场)=====
|
||||
green "【步骤1/5】清理脚本自身可能的阻塞进程"
|
||||
pkill -f "screen_clean_*" >/dev/null 2>&1 || true
|
||||
pkill -9 -f "pgrep -f SCREEN -S ${SCREEN_NAME}" >/dev/null 2>&1 || true
|
||||
|
||||
get_inner_procs() {
|
||||
local screen_pid=$1
|
||||
local procs=$(timeout 5 pstree -p "$screen_pid" 2>/dev/null | grep -oE '\([0-9]+\)' | tr -d '()' | grep -v "$screen_pid" | sort -u)
|
||||
if [ -z "$procs" ]; then
|
||||
procs=$(pgrep -f "SCREEN -S $SCREEN_NAME" 2>/dev/null | grep -v "$screen_pid")
|
||||
fi
|
||||
echo "$procs"
|
||||
}
|
||||
# ===== 非阻塞查找进程+会话(关键:延长超时到1秒,查更全)=====
|
||||
green "【步骤2/5】查找${SCREEN_NAME}相关进程/会话(非阻塞)"
|
||||
# 先查screen会话ID(1秒超时,避免漏查)
|
||||
SCREEN_SESS=$(timeout 1 screen -ls 2>/dev/null | grep -E "[0-9]+\\.${SCREEN_NAME}" | grep -v "Dead" | awk '{print $1}' || true)
|
||||
# 再查进程PID
|
||||
SCREEN_PIDS=$(timeout 1 pgrep -f "SCREEN -S ${SCREEN_NAME}" | grep -v $$ || true)
|
||||
|
||||
screen_send_cmd() {
|
||||
local cmd="$1"
|
||||
local screen_full_id="$2"
|
||||
# ^M需手动生成:Ctrl+v+回车
|
||||
screen -S "$screen_full_id" -p 0 -X stuff "${cmd}^M"
|
||||
sleep 1
|
||||
}
|
||||
|
||||
# ========== 核心修复:给screen -ls加超时,避免卡住 ==========
|
||||
echo "===== 检测screen会话(5秒超时) ====="
|
||||
# 关键修改:给整个提取命令加5秒超时,超时则直接设为空
|
||||
SCREEN_FULL_ID=$(timeout 5 screen -ls 2>/dev/null | grep -E "[0-9]+\.$SCREEN_NAME" | grep -v "Dead\|Invalid" | head -1 | awk '{print $1}')
|
||||
|
||||
# 无论是否超时/卡住,只要SCREEN_FULL_ID为空,就直接走后续
|
||||
if [ -z "$SCREEN_FULL_ID" ]; then
|
||||
echo "ℹ️ 未找到$SCREEN_NAME会话(或screen -ls执行超时),直接执行后续脚本"
|
||||
# 合并需要清理的目标
|
||||
if [ -z "${SCREEN_SESS}" ] && [ -z "${SCREEN_PIDS}" ]; then
|
||||
green "✅ 未找到${SCREEN_NAME}相关进程/会话,无需清理"
|
||||
else
|
||||
# 找到会话:执行终止逻辑
|
||||
SCREEN_PID=$(echo "$SCREEN_FULL_ID" | cut -d. -f1)
|
||||
echo "✅ 找到$SCREEN_NAME,主PID:$SCREEN_PID | 完整ID:$SCREEN_FULL_ID"
|
||||
|
||||
# 导出退出前日志
|
||||
echo -e "\n===== 【退出前】$SCREEN_NAME 内程序实时log ====="
|
||||
screen -S "$SCREEN_FULL_ID" -p 0 -X hardcopy -h "$LOG_FILE" 2>/dev/null
|
||||
cat "$LOG_FILE"
|
||||
|
||||
# 给子进程发SIGTERM并等待
|
||||
echo -e "\n===== 给子进程发优雅退出信号(SIGTERM) ====="
|
||||
INNER_PROCS=$(get_inner_procs "$SCREEN_PID")
|
||||
if [ -z "$INNER_PROCS" ]; then
|
||||
echo "ℹ 未检测到$SCREEN_NAME下的子进程"
|
||||
else
|
||||
echo "待处理子进程:$INNER_PROCS"
|
||||
for pid in $INNER_PROCS; do
|
||||
if pid_is_alive "$pid"; then
|
||||
echo -n "📌 终止进程$pid并等待退出:"
|
||||
kill -15 "$pid"
|
||||
if [ $? -eq 0 ]; then
|
||||
wait_for_process_exit "$pid"
|
||||
else
|
||||
echo "❌ 进程$pid:发送SIGTERM失败"
|
||||
fi
|
||||
else
|
||||
echo "ℹ 进程$pid:已不存在,跳过"
|
||||
fi
|
||||
yellow "⚠️ 找到${SCREEN_NAME}会话:${SCREEN_SESS:-无}"
|
||||
yellow "⚠️ 找到${SCREEN_NAME}进程:${SCREEN_PIDS:-无}"
|
||||
|
||||
# ===== 非阻塞强制清理(先清会话,再清进程)=====
|
||||
green "【步骤3/5】强制清理${SCREEN_NAME}进程及会话"
|
||||
# 1. 清理所有screen会话
|
||||
if [ -n "${SCREEN_SESS}" ]; then
|
||||
for sess in ${SCREEN_SESS}; do
|
||||
yellow "🔧 清理会话:${sess}"
|
||||
clean_screen_sessions "${sess}"
|
||||
done
|
||||
fi
|
||||
|
||||
# 验证子进程退出状态
|
||||
echo -e "\n===== 验证子进程退出状态 ====="
|
||||
REMAIN_PROCS=$(get_inner_procs "$SCREEN_PID")
|
||||
if [ -z "$REMAIN_PROCS" ]; then
|
||||
echo "✅ $SCREEN_NAME内部所有程序已退出"
|
||||
else
|
||||
echo "⚠️ 仍有残留进程:$REMAIN_PROCS"
|
||||
# 2. 清理剩余进程(兜底)
|
||||
if [ -n "${SCREEN_PIDS}" ]; then
|
||||
for pid in ${SCREEN_PIDS}; do
|
||||
yellow "🔧 清理进程:${pid}"
|
||||
kill -9 "${pid}" >/dev/null 2>&1 || true
|
||||
pkill -9 -P "${pid}" >/dev/null 2>&1 || true
|
||||
done
|
||||
fi
|
||||
|
||||
# 投递exit命令退出screen
|
||||
echo -e "\n===== 优雅退出screen会话 ====="
|
||||
echo "向$SCREEN_NAME投递exit命令..."
|
||||
screen_send_cmd "exit" "$SCREEN_FULL_ID"
|
||||
|
||||
# 等待并验证最终状态
|
||||
echo -n "等待screen会话自动退出"
|
||||
begin=$(date +%s)
|
||||
while timeout 1 screen -ls "$SCREEN_NAME" 2>/dev/null | grep -q -E "[0-9]+\.$SCREEN_NAME"; do
|
||||
echo -n "."
|
||||
sleep 1
|
||||
if [ $((date +%s - begin)) -gt 30 ]; then
|
||||
echo -e "\n⚠️ 等待screen退出超时(30秒)"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "\n===== 最终验证 ====="
|
||||
if timeout 1 screen -ls "$SCREEN_NAME" 2>/dev/null | grep -q -E "[0-9]+\.$SCREEN_NAME"; then
|
||||
echo "❌ $SCREEN_NAME会话最终仍未退出"
|
||||
|
||||
# 短暂等待(0.5秒,非阻塞)
|
||||
sleep 0.5
|
||||
|
||||
# ===== 验证清理结果(查会话+进程,双重验证)=====
|
||||
green "【步骤4/5】验证清理结果(会话+进程双重检查)"
|
||||
FINAL_SESS=$(timeout 1 screen -ls 2>/dev/null | grep -E "[0-9]+\\.${SCREEN_NAME}" | grep -v "Dead" || true)
|
||||
FINAL_PIDS=$(timeout 1 pgrep -f "SCREEN -S ${SCREEN_NAME}" | grep -v $$ || true)
|
||||
|
||||
if [ -z "${FINAL_SESS}" ] && [ -z "${FINAL_PIDS}" ]; then
|
||||
green "✅ ${SCREEN_NAME}进程/会话已全部清理完成"
|
||||
else
|
||||
echo "✅ $SCREEN_NAME会话已完全退出"
|
||||
red "❌ 仍有残留:会话[${FINAL_SESS}] 进程[${FINAL_PIDS}],再次强制清理"
|
||||
# 终极兜底:强制杀死所有相关进程
|
||||
pkill -9 -f "${SCREEN_NAME}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# ========== 后续脚本:必执行,永不卡住 ==========
|
||||
echo -e "\n===== 终止logic会话流程结束,继续执行后续脚本 ====="
|
||||
# 示例后续逻辑
|
||||
# echo "执行后续任务:备份日志、启动新进程等..."
|
||||
# ===== 最终收尾 =====
|
||||
green "【步骤5/5】${SCREEN_NAME}会话清理流程结束"
|
||||
green "✅ 自动化部署后续流程可正常执行"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user