fix(deploy): detect service port with ss
This commit is contained in:
+53
-15
@@ -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 # 再启新
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user