This commit is contained in:
Arvin
2026-03-21 13:58:10 +08:00
parent f62ea80d43
commit dda67b180d
72 changed files with 848 additions and 1181 deletions

View File

@ -1,36 +1,49 @@
#!/bin/bash
#!/usr/bin/env bash
set -euo pipefail
PORT_CHECK_WARNED=${PORT_CHECK_WARNED:-0}
# =========================
# 判断端口是否被占用(更稳)
# =========================
is_port_in_use() {
local port="$1"
if command -v ss >/dev/null 2>&1; then
ss -lnt | awk '{print $4}' | grep -E "(:|\.)${port}$" >/dev/null 2>&1
ss -lnt 2>/dev/null | awk '{print $4}' | grep -E "[:.]${port}$" >/dev/null 2>&1
return $?
fi
if command -v netstat >/dev/null 2>&1; then
netstat -lnt | awk '{print $4}' | grep -E "(:|\.)${port}$" >/dev/null 2>&1
netstat -lnt 2>/dev/null | awk '{print $4}' | grep -E "[:.]${port}$" >/dev/null 2>&1
return $?
fi
if command -v lsof >/dev/null 2>&1; then
lsof -iTCP -sTCP:LISTEN -P -n | awk '{print $9}' | grep -E "(:|\.)${port}$" >/dev/null 2>&1
lsof -iTCP -sTCP:LISTEN -P -n 2>/dev/null | awk '{print $9}' | grep -E "[:.]${port}$" >/dev/null 2>&1
return $?
fi
if [ "$PORT_CHECK_WARNED" -eq 0 ]; then
echo -e "\033[33m[WARN] 未找到端口检测工具,端口冲突检测可能不准确\033[0m" >&2
echo "[WARN] no port check tool found (ss/netstat/lsof)" >&2
PORT_CHECK_WARNED=1
fi
return 1
}
# =========================
# 找可用端口(优化版)
# =========================
find_available_port() {
local start_port=${1:-20000}
local end_port=${2:-65000}
local start="${1:-20000}"
local end="${2:-65000}"
local port
# 优先随机尝试
if command -v shuf >/dev/null 2>&1; then
for _ in {1..50}; do
port=$(shuf -i "${start_port}-${end_port}" -n 1)
for _ in {1..30}; do
port=$(shuf -i "${start}-${end}" -n 1)
if ! is_port_in_use "$port"; then
echo "$port"
return 0
@ -38,7 +51,8 @@ find_available_port() {
done
fi
for port in $(seq "$start_port" "$end_port"); do
# fallback 顺序扫描(限制范围避免慢)
for port in $(seq "$start" "$((start + 2000))"); do
if ! is_port_in_use "$port"; then
echo "$port"
return 0
@ -48,43 +62,56 @@ find_available_port() {
return 1
}
# =========================
# 解析端口值(核心函数)
# =========================
resolve_port_value() {
local name="$1"
local value="$2"
local resolved
# auto / 空
if [ -z "$value" ] || [ "$value" = "auto" ]; then
resolved=$(find_available_port)
if [ -z "$resolved" ]; then
resolved=$(find_available_port) || {
echo "[ERROR] ${name} failed to allocate port" >&2
return 1
fi
echo -e "\033[33m[WARN] ${name} 端口已自动分配为 ${resolved}\033[0m" >&2
}
echo "[WARN] ${name} auto assigned: ${resolved}" >&2
echo "$resolved"
return 0
fi
if [[ "$value" =~ ^[0-9]+$ ]]; then
if is_port_in_use "$value"; then
resolved=$(find_available_port)
if [ -n "$resolved" ]; then
echo -e "\033[33m[WARN] ${name} 端口 ${value} 已被占用,已自动切换为 ${resolved}\033[0m" >&2
echo "$resolved"
return 0
fi
# 非数字
if ! [[ "$value" =~ ^[0-9]+$ ]]; then
echo "[ERROR] invalid port: $value" >&2
return 1
fi
# 被占用 → 自动替换
if is_port_in_use "$value"; then
resolved=$(find_available_port)
if [ -n "$resolved" ]; then
echo "[WARN] ${name} port ${value} in use, switched to ${resolved}" >&2
echo "$resolved"
return 0
fi
fi
echo "$value"
}
# =========================
# 解析 host:port
# =========================
resolve_host_port() {
local name="$1"
local raw="$2"
local default_host="$3"
local host
local port
if [ "$raw" = "auto" ] || [ -z "$raw" ]; then
if [ -z "$raw" ] || [ "$raw" = "auto" ]; then
host="$default_host"
port="auto"
else
@ -97,6 +124,10 @@ resolve_host_port() {
fi
fi
# host 兜底
[ -z "$host" ] && host="$default_host"
port=$(resolve_port_value "$name" "$port") || return 1
echo "${host}:${port}"
}
}