-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclose_api_server.sh
More file actions
executable file
·140 lines (119 loc) · 3.04 KB
/
close_api_server.sh
File metadata and controls
executable file
·140 lines (119 loc) · 3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage:
./close_api_server.sh [--port PORT] [--pid PID] [--force]
Defaults:
PORT: 8001
Behavior:
- If --pid is provided, stops that PID.
- Otherwise, finds the listening PID(s) on --port and stops them.
- By default, only stops processes whose cmdline contains "uvicorn" or "acestep.api_server".
Use --force to skip this safety check.
EOF
}
PORT="8002"
PID=""
FORCE="0"
while [[ $# -gt 0 ]]; do
case "$1" in
--port)
PORT="${2:-}"; shift 2 ;;
--pid)
PID="${2:-}"; shift 2 ;;
--force)
FORCE="1"; shift ;;
-h|--help)
usage; exit 0 ;;
*)
echo "Unknown argument: $1" >&2
usage
exit 2
;;
esac
done
if [[ -n "$PORT" ]] && ! [[ "$PORT" =~ ^[0-9]+$ ]]; then
echo "Invalid --port: $PORT" >&2
exit 2
fi
if [[ -n "$PID" ]] && ! [[ "$PID" =~ ^[0-9]+$ ]]; then
echo "Invalid --pid: $PID" >&2
exit 2
fi
_cmdline() {
local pid="$1"
if [[ -r "/proc/${pid}/cmdline" ]]; then
tr '\0' ' ' < "/proc/${pid}/cmdline" | sed 's/[[:space:]]\+/ /g' || true
else
echo ""
fi
}
_is_target_process() {
local pid="$1"
local cmd
cmd="$(_cmdline "$pid")"
[[ "$cmd" == *"uvicorn"* || "$cmd" == *"acestep.api_server"* ]]
}
_find_pids_by_port() {
local port="$1"
local pids=""
if command -v lsof >/dev/null 2>&1; then
pids="$(lsof -nP -t -iTCP:"$port" -sTCP:LISTEN 2>/dev/null | tr '\n' ' ' || true)"
elif command -v ss >/dev/null 2>&1; then
# 输出示例:LISTEN 0 4096 127.0.0.1:8001 ... users:("python",pid=12345,fd=3)
pids="$(ss -lptn "sport = :$port" 2>/dev/null | sed -n 's/.*pid=\([0-9]\+\).*/\1/p' | sort -u | tr '\n' ' ' || true)"
elif command -v netstat >/dev/null 2>&1; then
# 输出示例:tcp ... LISTEN 12345/python
pids="$(netstat -lntp 2>/dev/null | awk -v p=":${port}" '$4 ~ p && $6=="LISTEN" {split($7,a,"/"); if (a[1] ~ /^[0-9]+$/) print a[1]}' | sort -u | tr '\n' ' ' || true)"
elif command -v fuser >/dev/null 2>&1; then
pids="$(fuser -n tcp "$port" 2>/dev/null | tr '\n' ' ' || true)"
fi
echo "$pids"
}
_stop_pid() {
local pid="$1"
if ! kill -0 "$pid" 2>/dev/null; then
echo "PID $pid not running."
return 0
fi
if [[ "$FORCE" != "1" ]] && ! _is_target_process "$pid"; then
echo "Skip PID $pid (cmdline does not look like uvicorn/acestep.api_server). Use --force to stop anyway." >&2
echo "cmdline: $(_cmdline "$pid")" >&2
return 3
fi
echo "Stopping PID $pid..."
kill -TERM "$pid" 2>/dev/null || true
for _ in $(seq 1 30); do
if ! kill -0 "$pid" 2>/dev/null; then
echo "Stopped PID $pid."
return 0
fi
sleep 0.2
done
echo "PID $pid did not exit; sending SIGKILL..." >&2
kill -KILL "$pid" 2>/dev/null || true
sleep 0.1
if kill -0 "$pid" 2>/dev/null; then
echo "Failed to kill PID $pid." >&2
return 1
fi
echo "Killed PID $pid."
return 0
}
if [[ -n "$PID" ]]; then
_stop_pid "$PID"
exit $?
fi
pids="$(_find_pids_by_port "$PORT")"
if [[ -z "${pids// }" ]]; then
echo "No listening process found on port $PORT."
exit 0
fi
rc=0
for pid in $pids; do
if [[ -n "$pid" ]]; then
_stop_pid "$pid" || rc=$?
fi
done
exit "$rc"