fix(deploy): detect service port with ss

This commit is contained in:
2026-06-18 11:49:39 +08:00
parent b09795a7b8
commit 428402d4b1
+53 -15
View File
@@ -13,6 +13,7 @@ CURRENT_BRANCH=""
START_PORT="" START_PORT=""
BUILD_EXIT=0 BUILD_EXIT=0
STOP_WAIT_SECONDS=3 STOP_WAIT_SECONDS=3
STOP_VERIFY_RETRIES=3
resolve_repo_context() { resolve_repo_context() {
GIT_DIR_ABS="$(git rev-parse --absolute-git-dir 2>/dev/null)" GIT_DIR_ABS="$(git rev-parse --absolute-git-dir 2>/dev/null)"
@@ -106,19 +107,55 @@ run_build() {
# ============================================================ # ============================================================
# 6. stop_existing_next —— 强杀当前分支端口上的旧进程 # 6. stop_existing_next —— 强杀当前分支端口上的旧进程
# 1) 查找占用 START_PORT 的进程 # 1) 使用 ss 查找占用 START_PORT 的进程
# 2) 直接 SIGKILL,避免旧服务 drain 太久导致新服务无法绑定端口 # 2) 直接 SIGKILL,避免旧服务 drain 太久导致新服务无法绑定端口
# 3) 等待 STOP_WAIT_SECONDS,让系统释放端口 # 3) 等待 STOP_WAIT_SECONDS,让系统释放端口
# 4) 复查端口占用并再次强杀残留 # 4) 循环复查端口占用并再次强杀残留
# ============================================================ # ============================================================
find_port_pids() { find_port_pids() {
if command -v lsof >/dev/null 2>&1; then if ! command -v ss >/dev/null 2>&1; then
lsof -ti tcp:"$START_PORT" 2>/dev/null || true echo "=== ss command not found; cannot inspect port $START_PORT ===" >> "$LOG_FILE"
return return 0
fi fi
if command -v fuser >/dev/null 2>&1; then
fuser "$START_PORT"/tcp 2>/dev/null || true ss -tulnp 2>/dev/null \
| awk -v port=":$START_PORT" '$5 ~ port "$" { print }' \
| sed -n 's/.*pid=\([0-9][0-9]*\).*/\1/p' \
| sort -u
}
force_kill_pids() {
PIDS_TO_KILL="$1"
if [ -z "$PIDS_TO_KILL" ]; then
return 0
fi fi
echo "=== force kill PIDS: $PIDS_TO_KILL ===" >> "$LOG_FILE"
kill -9 $PIDS_TO_KILL 2>/dev/null || true
}
wait_for_port_release() {
RETRY=0
while [ "$RETRY" -lt "$STOP_VERIFY_RETRIES" ]; do
REMAINING_PIDS="$(find_port_pids)"
if [ -z "$REMAINING_PIDS" ]; then
echo "=== port $START_PORT released ===" >> "$LOG_FILE"
return 0
fi
echo "=== port $START_PORT still busy, retry=$RETRY, pids=$REMAINING_PIDS ===" >> "$LOG_FILE"
force_kill_pids "$REMAINING_PIDS"
sleep "$STOP_WAIT_SECONDS"
RETRY=$((RETRY + 1))
done
REMAINING_PIDS="$(find_port_pids)"
if [ -n "$REMAINING_PIDS" ]; then
echo "=== stop FAILED: port $START_PORT still occupied by PIDS: $REMAINING_PIDS ===" >> "$LOG_FILE"
return 1
fi
echo "=== port $START_PORT released ===" >> "$LOG_FILE"
return 0
} }
stop_existing_next() { stop_existing_next() {
@@ -126,23 +163,22 @@ stop_existing_next() {
PIDS="$(find_port_pids)" PIDS="$(find_port_pids)"
if [ -n "$PIDS" ]; then if [ -n "$PIDS" ]; then
echo "=== force kill PIDS: $PIDS ===" >> "$LOG_FILE" force_kill_pids "$PIDS"
kill -9 $PIDS 2>/dev/null || true
else else
echo "=== no process found on port $START_PORT ===" >> "$LOG_FILE" echo "=== no process found on port $START_PORT ===" >> "$LOG_FILE"
fi fi
sleep "$STOP_WAIT_SECONDS" sleep "$STOP_WAIT_SECONDS"
REMAINING_PIDS="$(find_port_pids)" if ! wait_for_port_release; then
if [ -n "$REMAINING_PIDS" ]; then echo "=== stop ABORT @ $(date +%Y-%m-%dT%H:%M:%S%z) ===" >> "$LOG_FILE"
echo "=== force kill remaining PIDS: $REMAINING_PIDS ===" >> "$LOG_FILE" echo "" >> "$LOG_FILE"
kill -9 $REMAINING_PIDS 2>/dev/null || true return 1
sleep "$STOP_WAIT_SECONDS"
fi fi
echo "=== stop DONE @ $(date +%Y-%m-%dT%H:%M:%S%z) ===" >> "$LOG_FILE" echo "=== stop DONE @ $(date +%Y-%m-%dT%H:%M:%S%z) ===" >> "$LOG_FILE"
echo "" >> "$LOG_FILE" echo "" >> "$LOG_FILE"
return 0
} }
launch_next() { launch_next() {
@@ -177,7 +213,9 @@ main() {
exit $BUILD_EXIT # build 失败 → 不启 start(避免用旧 .next 跑新代码) exit $BUILD_EXIT # build 失败 → 不启 start(避免用旧 .next 跑新代码)
fi fi
stop_existing_next # build 成功 → 先关旧进程 if ! stop_existing_next; then
exit 1 # 端口未释放 → 不启动新服务,避免 EADDRINUSE
fi
launch_next # 再启新 launch_next # 再启新
} }