From 641f212400a42bb13064f0a724a753ec86616e5e Mon Sep 17 00:00:00 2001 From: Olia Lisa Date: Wed, 14 Jan 2026 17:25:19 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9F=A5=E6=89=BE=E7=A9=BA?= =?UTF-8?q?=E9=97=B2=E7=AB=AF=E5=8F=A3=E7=9A=84=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=9A=8F=E6=9C=BA=E5=B0=9D=E8=AF=95=E6=AC=A1?= =?UTF-8?q?=E6=95=B0=E5=92=8C=E9=94=99=E8=AF=AF=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/update_port.sh | 58 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/bin/update_port.sh b/bin/update_port.sh index a3da481..45cfd62 100644 --- a/bin/update_port.sh +++ b/bin/update_port.sh @@ -1,46 +1,76 @@ #!/bin/bash -# 查找空闲端口 + +# 查找随机空闲端口 +# 用途: +# 在指定端口范围内,随机选择一个当前未被监听(TCP/UDP)的端口 +# 参数: +# $1: 起始端口(默认 10001) +# $2: 结束端口(默认 65535) +# $3: 最大随机尝试次数(默认 100) find_free_port() { local start="${1:-10001}" local max="${2:-65535}" + local attempts="${3:-100}" - # 收集当前监听端口(TCP + UDP) + # ------------------------------------------------------------ + # 收集当前正在监听的端口(TCP + UDP) + # 优先使用 ss,其次 netstat + # ------------------------------------------------------------ local used_ports raw if command -v ss >/dev/null 2>&1; then + # ss 输出示例: + # LISTEN 0 128 0.0.0.0:22 raw=$(ss -lntu 2>/dev/null || true) - used_ports=$(printf "%s\n" "$raw" | awk '{print $5}' | sed -n '2,$p' | sed -E 's/.*[:]//g' | sed '/^$/d') + used_ports=$(printf "%s\n" "$raw" \ + | awk '{print $5}' \ + | sed -E 's/.*[:]//g') elif command -v netstat >/dev/null 2>&1; then + # netstat 输出示例: + # tcp 0 0 0.0.0.0:22 raw=$(netstat -lntu 2>/dev/null || true) - used_ports=$(printf "%s\n" "$raw" | awk '{print $4}' | sed -n '2,$p' | sed -E 's/.*[:]//g' | sed '/^$/d') - elif command -v lsof >/dev/null 2>&1; then - raw=$(lsof -i -P -n 2>/dev/null || true) - used_ports=$(printf "%s\n" "$raw" | awk '/LISTEN/ {print $9}' | sed -E 's/.*[:]//g' | sed '/^$/d') + used_ports=$(printf "%s\n" "$raw" \ + | awk '{print $4}' \ + | sed -E 's/.*[:]//g') else - echo "Error: neither ss, netstat nor lsof is available to check listening ports." >&2 + echo "Error: ss or netstat is required to check listening ports." >&2 return 2 fi - # 用关联数组记录已占用端口(需要 bash 4+) + # ------------------------------------------------------------ + # 将已占用端口存入关联数组,便于 O(1) 判断 + # 需要 bash 4+ + # ------------------------------------------------------------ declare -A used_map local p for p in $used_ports; do - # 过滤掉非数字 + # 过滤非数字字段(如 *、:::) if [[ $p =~ ^[0-9]+$ ]]; then used_map["$p"]=1 fi done - # 从 start 到 max 逐个检查 - for ((port = start; port <= max; port++)); do + # ------------------------------------------------------------ + # 随机尝试若干次 + # 每次随机生成一个端口,只要未被监听就立即返回 + # ------------------------------------------------------------ + local port i + for ((i=0; i&2 + # ------------------------------------------------------------ + # 多次随机尝试后仍未找到可用端口 + # 通常意味着端口范围过小或已被大量占用 + # ------------------------------------------------------------ + echo "Error: no free port found after $attempts random attempts." >&2 return 1 }