Detect listening ports without ss via /dev/tcp fallback
ci / test-pg (pull_request) Successful in 1m0s
ci / test (pull_request) Failing after 1m6s

Why: the CI runner container has no iproute2, so port_listening went
blind: recover started a service onto a thief-held port and the health
probe hit the thief (HTTP 200), reporting a bogus start success.

Evidence: no-ss PATH simulation shows the fallback detects a bound port
and passes free ports; make test-governance rerun recorded on the task
card; CI on the new head is authoritative.

Impact: scripts/svc.sh port_listening only (ss stays primary when
present).

Refs: .task/feature-svc-autorecover.md
This commit is contained in:
2026-10-11 21:12:16 +00:00
parent b12e94dcd9
commit 9b5ecd57a2
2 changed files with 46 additions and 2 deletions
File diff suppressed because one or more lines are too long
+8 -2
View File
@@ -678,10 +678,16 @@ ports_recorded() {
return 1
}
# port_listening PORT:端口是否被监听。优先 ss;不可用或无命中时退化为 bash 内建
# /dev/tcp 连接探测(CI 最小容器无 iproute2 时端口检查会失明——2026-10-11 实测:
# thief 占口,recover 未识别照常启动,健康探测打到 thief 上误报已启动)。
port_listening() {
local p="$1"
command -v ss >/dev/null 2>&1 || return 1
ss -ltn 2>/dev/null | awk -v p=":$p" '$4 ~ p"$" {f=1} END {exit !f}'
if command -v ss >/dev/null 2>&1; then
ss -ltn 2>/dev/null | awk -v p=":$p" '$4 ~ p"$" {f=1} END {exit !f}' && return 0
fi
(exec 3<>"/dev/tcp/127.0.0.1/$p") 2>/dev/null && return 0
return 1
}
# derive_port NAME:由服务名确定性派生端口(8800+hash%300),冲突时在 8800..9099 递增。