检测端口冲突时区分 tcp 和 udp 端口,防止误报

Fix #1242
This commit is contained in:
Feng Yu
2026-03-22 23:21:41 +08:00
parent 21c4f8400b
commit 7ed66026be
3 changed files with 745 additions and 690 deletions

View File

@@ -43,36 +43,47 @@ checkrestart() {
# 检查端口冲突 # 检查端口冲突
checkport() { checkport() {
. "$CRASHDIR"/menus/check_port.sh
while true; do while true; do
# Before each round of checks begins, execute netstat only once and cache the results local conflict_found=0
# Avoid calling the system command once for each port local conflict_port=""
current_listening=$(netstat -ntul 2>&1) local conflict_info=""
conflict_found=0 conflict_info=$(check_port_with_info "$mix_port" tcp)
if [ $? -ne 0 ]; then
conflict_found=1
conflict_port="$mix_port"
fi
for portx in $dns_port $mix_port $redir_port $((redir_port + 1)) $db_port; do
# Use `grep` to search within the cached variables instead of re-running `netstat`
conflict_line=$(echo "$current_listening" | grep ":$portx ")
if [ -n "$conflict_line" ]; then
comp_box "$portx】:$MENU_PORT_CONFLICT_TITLE" \
"\033[0m$(echo "$conflict_line" | head -n 1)\033[0m" \
"\033[36m$MENU_PORT_CONFLICT_HINT\033[0m"
. "$CRASHDIR"/menus/2_settings.sh && set_adv_config
. "$CRASHDIR"/libs/get_config.sh
# Mark conflict and exit the for loop, triggering the while loop to restart the check
# This replaces the original recursive call to `checkport`
conflict_found=1
break
fi
done
# If no conflicts are found after the entire for loop completes,
# the while loop exits and the function terminates.
if [ "$conflict_found" -eq 0 ]; then if [ "$conflict_found" -eq 0 ]; then
conflict_info=$(check_port_with_info "$redir_port" tcp)
[ $? -ne 0 ] && conflict_found=1 && conflict_port="$redir_port"
fi
if [ "$conflict_found" -eq 0 ]; then
conflict_info=$(check_port_with_info "$((redir_port + 1))" tcp)
[ $? -ne 0 ] && conflict_found=1 && conflict_port="$((redir_port + 1))"
fi
if [ "$conflict_found" -eq 0 ]; then
conflict_info=$(check_port_with_info "$dns_port" all)
[ $? -ne 0 ] && conflict_found=1 && conflict_port="$dns_port"
fi
if [ "$conflict_found" -eq 0 ]; then
conflict_info=$(check_port_with_info "$db_port" tcp)
[ $? -ne 0 ] && conflict_found=1 && conflict_port="$db_port"
fi
if [ "$conflict_found" -eq 1 ]; then
comp_box "$conflict_port】:$MENU_PORT_CONFLICT_TITLE" \
"\033[0m$conflict_info\033[0m" \
"\033[36m$MENU_PORT_CONFLICT_HINT\033[0m"
. "$CRASHDIR"/menus/2_settings.sh && set_adv_config
. "$CRASHDIR"/libs/get_config.sh
else
break break
fi fi
done done
@@ -195,17 +206,17 @@ main_menu() {
while true; do while true; do
ckstatus ckstatus
btm_box "1) \033[32m$MENU_MAIN_1\033[0m"\ btm_box "1) \033[32m$MENU_MAIN_1\033[0m" \
"2) \033[36m$MENU_MAIN_2\033[0m"\ "2) \033[36m$MENU_MAIN_2\033[0m" \
"3) \033[31m$MENU_MAIN_3\033[0m"\ "3) \033[31m$MENU_MAIN_3\033[0m" \
"4) \033[33m$MENU_MAIN_4\033[0m"\ "4) \033[33m$MENU_MAIN_4\033[0m" \
"5) \033[32m$MENU_MAIN_5\033[0m"\ "5) \033[32m$MENU_MAIN_5\033[0m" \
"6) \033[36m$MENU_MAIN_6\033[0m"\ "6) \033[36m$MENU_MAIN_6\033[0m" \
"7) \033[33m$MENU_MAIN_7\033[0m"\ "7) \033[33m$MENU_MAIN_7\033[0m" \
"8) $MENU_MAIN_8"\ "8) $MENU_MAIN_8" \
"9) \033[32m$MENU_MAIN_9\033[0m"\ "9) \033[32m$MENU_MAIN_9\033[0m" \
""\ "" \
"0) $MENU_MAIN_0" "0) $MENU_MAIN_0"
read -r -p "$MENU_MAIN_PROMPT" num read -r -p "$MENU_MAIN_PROMPT" num
case "$num" in case "$num" in

File diff suppressed because it is too large Load Diff

View File

@@ -3,17 +3,60 @@
load_lang check_port load_lang check_port
check_port() { _get_netstat_cmd() {
if [ "$1" -gt 65535 ] || [ "$1" -le 1 ]; then case "$1" in
msg_alert "\033[31m$CHECK_PORT_RANGE_ERR\033[0m" tcp) echo "netstat -ntl" ;;
return 1 udp) echo "netstat -nul" ;;
elif echo "|$mix_port|$redir_port|$dns_port|$db_port|" | grep -q "|$1|"; then *) echo "netstat -ntul" ;;
msg_alert "\033[31m$CHECK_PORT_DUP_ERR\033[0m" esac
return 1 }
elif netstat -ntul | grep -q ":$1[[:space:]]"; then
msg_alert "\033[31m$CHECK_PORT_OCCUPIED_ERR\033[0m" check_port() {
return 1 local port="$1"
else local protocol="${2:-all}"
return 0
fi if [ "$port" -gt 65535 ] || [ "$port" -le 1 ]; then
msg_alert "\033[31m$CHECK_PORT_RANGE_ERR\033[0m"
return 1
fi
local current_port_name=""
case "$port" in
"$mix_port") current_port_name="mix_port" ;;
"$redir_port") current_port_name="redir_port" ;;
"$dns_port") current_port_name="dns_port" ;;
"$db_port") current_port_name="db_port" ;;
esac
if [ -z "$current_port_name" ] && echo "|$mix_port|$redir_port|$dns_port|$db_port|" | grep -q "|$port|"; then
msg_alert "\033[31m$CHECK_PORT_DUP_ERR\033[0m"
return 1
fi
local check_cmd
check_cmd=$(_get_netstat_cmd "$protocol")
if $check_cmd 2>/dev/null | grep -q ":${port}[[:space:]]"; then
msg_alert "\033[31m$CHECK_PORT_OCCUPIED_ERR\033[0m"
return 1
fi
return 0
}
check_port_with_info() {
local port="$1"
local protocol="${2:-all}"
local check_cmd
check_cmd=$(_get_netstat_cmd "$protocol")
local conflict_line
conflict_line=$($check_cmd 2>/dev/null | grep ":${port}[[:space:]]" | head -n 1)
if [ -n "$conflict_line" ]; then
echo "$conflict_line"
return 1
fi
return 0
} }