From 428402d4b1900faaa77c80f624cdfc6bc7aa8957 Mon Sep 17 00:00:00 2001 From: chenhang Date: Thu, 18 Jun 2026 11:49:39 +0800 Subject: [PATCH] fix(deploy): detect service port with ss --- .githooks/post-receive | 68 ++++++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/.githooks/post-receive b/.githooks/post-receive index cc6a6b6c..f7b6e678 100755 --- a/.githooks/post-receive +++ b/.githooks/post-receive @@ -13,6 +13,7 @@ CURRENT_BRANCH="" START_PORT="" BUILD_EXIT=0 STOP_WAIT_SECONDS=3 +STOP_VERIFY_RETRIES=3 resolve_repo_context() { GIT_DIR_ABS="$(git rev-parse --absolute-git-dir 2>/dev/null)" @@ -106,19 +107,55 @@ run_build() { # ============================================================ # 6. stop_existing_next —— 强杀当前分支端口上的旧进程 -# 1) 查找占用 START_PORT 的进程 +# 1) 使用 ss 查找占用 START_PORT 的进程 # 2) 直接 SIGKILL,避免旧服务 drain 太久导致新服务无法绑定端口 # 3) 等待 STOP_WAIT_SECONDS,让系统释放端口 -# 4) 复查端口占用并再次强杀残留 +# 4) 循环复查端口占用并再次强杀残留 # ============================================================ find_port_pids() { - if command -v lsof >/dev/null 2>&1; then - lsof -ti tcp:"$START_PORT" 2>/dev/null || true - return + if ! command -v ss >/dev/null 2>&1; then + echo "=== ss command not found; cannot inspect port $START_PORT ===" >> "$LOG_FILE" + return 0 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 + 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() { @@ -126,23 +163,22 @@ stop_existing_next() { PIDS="$(find_port_pids)" if [ -n "$PIDS" ]; then - echo "=== force kill PIDS: $PIDS ===" >> "$LOG_FILE" - kill -9 $PIDS 2>/dev/null || true + force_kill_pids "$PIDS" else echo "=== no process found on port $START_PORT ===" >> "$LOG_FILE" fi sleep "$STOP_WAIT_SECONDS" - REMAINING_PIDS="$(find_port_pids)" - if [ -n "$REMAINING_PIDS" ]; then - echo "=== force kill remaining PIDS: $REMAINING_PIDS ===" >> "$LOG_FILE" - kill -9 $REMAINING_PIDS 2>/dev/null || true - sleep "$STOP_WAIT_SECONDS" + if ! wait_for_port_release; then + echo "=== stop ABORT @ $(date +%Y-%m-%dT%H:%M:%S%z) ===" >> "$LOG_FILE" + echo "" >> "$LOG_FILE" + return 1 fi echo "=== stop DONE @ $(date +%Y-%m-%dT%H:%M:%S%z) ===" >> "$LOG_FILE" echo "" >> "$LOG_FILE" + return 0 } launch_next() { @@ -177,7 +213,9 @@ main() { exit $BUILD_EXIT # build 失败 → 不启 start(避免用旧 .next 跑新代码) fi - stop_existing_next # build 成功 → 先关旧进程 + if ! stop_existing_next; then + exit 1 # 端口未释放 → 不启动新服务,避免 EADDRINUSE + fi launch_next # 再启新 }