mirror of
https://github.com/wnlen/clash-for-linux.git
synced 2026-02-04 10:11:28 +08:00
103 lines
2.1 KiB
Bash
103 lines
2.1 KiB
Bash
#!/bin/bash
|
|
|
|
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
|
|
return $?
|
|
fi
|
|
if command -v netstat >/dev/null 2>&1; then
|
|
netstat -lnt | 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
|
|
return $?
|
|
fi
|
|
if [ "$PORT_CHECK_WARNED" -eq 0 ]; then
|
|
echo -e "\033[33m[WARN] 未找到端口检测工具,端口冲突检测可能不准确\033[0m" >&2
|
|
PORT_CHECK_WARNED=1
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
find_available_port() {
|
|
local start_port=${1:-20000}
|
|
local end_port=${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)
|
|
if ! is_port_in_use "$port"; then
|
|
echo "$port"
|
|
return 0
|
|
fi
|
|
done
|
|
fi
|
|
|
|
for port in $(seq "$start_port" "$end_port"); do
|
|
if ! is_port_in_use "$port"; then
|
|
echo "$port"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
resolve_port_value() {
|
|
local name="$1"
|
|
local value="$2"
|
|
local resolved
|
|
|
|
if [ -z "$value" ] || [ "$value" = "auto" ]; then
|
|
resolved=$(find_available_port)
|
|
if [ -z "$resolved" ]; then
|
|
return 1
|
|
fi
|
|
echo -e "\033[33m[WARN] ${name} 端口已自动分配为 ${resolved}\033[0m" >&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
|
|
fi
|
|
fi
|
|
|
|
echo "$value"
|
|
}
|
|
|
|
resolve_host_port() {
|
|
local name="$1"
|
|
local raw="$2"
|
|
local default_host="$3"
|
|
local host
|
|
local port
|
|
|
|
if [ "$raw" = "auto" ] || [ -z "$raw" ]; then
|
|
host="$default_host"
|
|
port="auto"
|
|
else
|
|
if [[ "$raw" == *:* ]]; then
|
|
host="${raw%:*}"
|
|
port="${raw##*:}"
|
|
else
|
|
host="$default_host"
|
|
port="$raw"
|
|
fi
|
|
fi
|
|
|
|
port=$(resolve_port_value "$name" "$port") || return 1
|
|
echo "${host}:${port}"
|
|
}
|