release: bump version to 0.48.0

This commit is contained in:
linkong
2026-05-07 18:06:06 +08:00
parent 421234301a
commit bb9183b8a4
51 changed files with 4609 additions and 400 deletions

View File

@@ -1153,6 +1153,7 @@ fail_unreleased_port() {
if [ -z "$(collect_port_pids "$port" || true)" ]; then
log_error "端口 ${port} 当前环境内未发现占用进程,但端口仍不可用,请检查宿主机或外部环境占用"
print_port_listener_details "$port"
else
log_error "端口 ${port} 清理失败,请检查占用进程"
if command -v lsof >/dev/null 2>&1; then
@@ -1160,6 +1161,7 @@ fail_unreleased_port() {
elif command -v ss >/dev/null 2>&1; then
ss -ltnp "( sport = :${port} )" 2>/dev/null || true
fi
print_windows_port_listener_details "$port" || true
fi
exit 1
@@ -1473,27 +1475,25 @@ terminate_process_tree() {
can_bind_port() {
local port="$1"
if command -v ss >/dev/null 2>&1; then
! ss -tlnH 2>/dev/null | awk '{print $4}' | grep -qE ":${port}$"
return
fi
if command -v lsof >/dev/null 2>&1; then
[ -z "$(lsof -tiTCP:"${port}" -sTCP:LISTEN 2>/dev/null)" ]
return
fi
python3 - "$port" <<'PY' >/dev/null 2>&1
if command -v python3 >/dev/null 2>&1; then
python3 - "$port" <<'PY' >/dev/null 2>&1
import socket
import sys
port = int(sys.argv[1])
sockets = []
try:
for family, host in ((socket.AF_INET, "127.0.0.1"), (socket.AF_INET6, "::1")):
for family, host in ((socket.AF_INET, "0.0.0.0"), (socket.AF_INET6, "::")):
try:
sock = socket.socket(family)
if family == socket.AF_INET6 and hasattr(socket, "IPV6_V6ONLY"):
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
sock.bind((host, port))
sockets.append(sock)
except OSError:
except OSError as exc:
if getattr(exc, "errno", None) in (socket.EAFNOSUPPORT, getattr(socket, "EADDRNOTAVAIL", -1)):
continue
raise
finally:
for sock in sockets:
@@ -1502,6 +1502,17 @@ finally:
except OSError:
pass
PY
return
fi
if command -v ss >/dev/null 2>&1; then
! ss -tlnH 2>/dev/null | awk '{print $4}' | grep -qE ":${port}$"
return
fi
if command -v lsof >/dev/null 2>&1; then
[ -z "$(lsof -tiTCP:"${port}" -sTCP:LISTEN 2>/dev/null)" ]
return
fi
}
wait_for_port_release() {
@@ -1574,6 +1585,38 @@ backend_log_indicates_port_conflict() {
grep -Eiq "Address already in use|Errno 98" "$log_file" 2>/dev/null
}
print_windows_port_listener_details() {
local port="$1"
local output=""
command -v powershell.exe >/dev/null 2>&1 || return 1
output="$(
powershell.exe -NoProfile -Command "
\$ErrorActionPreference = 'SilentlyContinue'
\$port = [int]${port}
\$connections = Get-NetTCPConnection -LocalPort \$port -State Listen
foreach (\$connection in \$connections) {
\$owningProcessId = \$connection.OwningProcess
\$process = Get-CimInstance Win32_Process -Filter \"ProcessId=\$owningProcessId\"
\$services = Get-CimInstance Win32_Service | Where-Object { \$_.ProcessId -eq \$owningProcessId } | Select-Object -ExpandProperty Name
\$processName = if (\$process.Name) { \$process.Name } else { 'unknown' }
\$serviceText = if (\$services) { ' services=' + (\$services -join ',') } else { '' }
'Windows listener: {0}:{1} pid={2} process={3}{4}' -f \$connection.LocalAddress, \$connection.LocalPort, \$owningProcessId, \$processName, \$serviceText
}
" 2>/dev/null | tr -d '\r'
)"
[ -n "$output" ] || return 1
while IFS= read -r line; do
[ -n "$line" ] || continue
printf "${DIM} %s${NC}\n" "$line"
done <<EOF
$output
EOF
return 0
}
print_port_listener_details() {
local port="$1"
local found=0
@@ -1609,6 +1652,10 @@ EOF
found=1
done
if print_windows_port_listener_details "$port"; then
found=1
fi
if [ "$found" -eq 0 ]; then
log_note "未能在当前环境内定位端口 ${port} 的监听进程,可能被宿主机或外部网络命名空间占用。"
fi