From f28bf1b7ec203532652583adcc151c96ec32abe5 Mon Sep 17 00:00:00 2001 From: Arvin <62139570+wnlen@users.noreply.github.com> Date: Tue, 14 Apr 2026 11:36:09 +0800 Subject: [PATCH] Improve install messaging for mixed-port bind denied --- scripts/core/common.sh | 99 +++++++++++++++++++++++++++++++++++++++++- scripts/init/script.sh | 16 ++++++- 2 files changed, 112 insertions(+), 3 deletions(-) diff --git a/scripts/core/common.sh b/scripts/core/common.sh index 7693391..62ede3a 100644 --- a/scripts/core/common.sh +++ b/scripts/core/common.sh @@ -2618,7 +2618,7 @@ remove_alias_command_wrappers() { } install_status_text() { - local has_subscription install_ready runtime_ready controller_ready build_status + local has_subscription install_ready runtime_ready controller_ready build_status bind_failure_kind local live_runtime="false" local live_controller="false" @@ -2632,6 +2632,7 @@ install_status_text() { runtime_ready="$(install_verify_runtime_ready 2>/dev/null || true)" controller_ready="$(install_verify_controller_ready 2>/dev/null || true)" build_status="$(read_build_value "BUILD_LAST_STATUS" 2>/dev/null || true)" + bind_failure_kind="$(install_mixed_port_bind_failure_kind 2>/dev/null || true)" if status_is_running 2>/dev/null; then live_runtime="true" @@ -2651,6 +2652,11 @@ install_status_text() { return 0 fi + if [ -n "${bind_failure_kind:-}" ]; then + echo "broken" + return 0 + fi + if [ "${live_runtime:-false}" = "true" ] && [ "${live_controller:-false}" = "true" ]; then echo "ready" return 0 @@ -2672,6 +2678,72 @@ install_status_text() { echo "verifying" } +install_mixed_port_bind_failure_line() { + local log_file="$LOG_DIR/mihomo.out.log" + local mixed_port line + + [ -f "$log_file" ] || return 1 + runtime_config_exists 2>/dev/null || return 1 + + mixed_port="$(runtime_config_mixed_port 2>/dev/null || true)" + if [ -n "${mixed_port:-}" ] && [ "$mixed_port" != "null" ]; then + line="$(grep -Ei "Start Mixed.*server error: listen tcp .*:${mixed_port}:.*(operation not permitted|permission denied|address already in use)" "$log_file" 2>/dev/null | tail -n 1 || true)" + fi + + if [ -z "${line:-}" ]; then + line="$(grep -Ei 'Start Mixed.*server error: listen tcp .*:.*(operation not permitted|permission denied|address already in use)' "$log_file" 2>/dev/null | tail -n 1 || true)" + fi + + [ -n "${line:-}" ] || return 1 + printf '%s\n' "$line" +} + +install_mixed_port_bind_failure_kind() { + local line lower + + line="$(install_mixed_port_bind_failure_line 2>/dev/null || true)" + [ -n "${line:-}" ] || return 1 + + lower="$(printf '%s' "$line" | tr '[:upper:]' '[:lower:]')" + case "$lower" in + *"address already in use"*) + echo "address_in_use" + ;; + *"operation not permitted"*|*"permission denied"*) + echo "bind_denied" + ;; + *) + echo "bind_failed" + ;; + esac +} + +install_mixed_port_bind_failure_port() { + local port line + + port="$(runtime_config_mixed_port 2>/dev/null || true)" + if runtime_port_value_is_valid "$port"; then + echo "$port" + return 0 + fi + + line="$(install_mixed_port_bind_failure_line 2>/dev/null || true)" + [ -n "${line:-}" ] || return 1 + printf '%s\n' "$line" | grep -Eo ':[0-9]+:' | tail -n 1 | tr -d ':' +} + +install_mixed_port_bind_observation_line() { + local mixed_port controller_port + + mixed_port="$(install_mixed_port_bind_failure_port 2>/dev/null || true)" + controller_port="$(runtime_config_controller_port 2>/dev/null || true)" + + if proxy_controller_reachable 2>/dev/null \ + || { runtime_port_value_is_valid "$controller_port" && is_port_in_use "$controller_port"; }; then + echo "配置已加载,控制器已启动,仅代理端口 ${mixed_port:-unknown} 绑定失败;这不是订阅或配置主链失败" + fi +} + install_status_label() { case "$(install_status_text)" in ready) echo "ready" ;; @@ -2715,9 +2787,10 @@ install_default_next_action() { } install_runtime_brief_line() { - local status_text mixed_port controller controller_display + local status_text mixed_port controller controller_display bind_failure_kind status_text="$(install_status_text)" + bind_failure_kind="$(install_mixed_port_bind_failure_kind 2>/dev/null || true)" mixed_port="$(install_plan_mixed_port 2>/dev/null || true)" [ -n "${mixed_port:-}" ] || mixed_port="$(read_env_value "MIXED_PORT" 2>/dev/null || echo "7890")" @@ -2750,6 +2823,15 @@ install_runtime_brief_line() { ;; broken) echo "❗ 当前状态:broken" + case "${bind_failure_kind:-}" in + bind_denied) + echo "🚫 代理端口绑定被系统拒绝(非端口冲突)" + echo "📌 修改端口通常无法解决,请先排查当前环境限制" + ;; + address_in_use) + echo "⚠️ 代理端口存在冲突(address already in use)" + ;; + esac ;; *) echo "⚪ 当前状态:unknown" @@ -2827,6 +2909,19 @@ print_install_summary() { echo "📦 订阅:$subscription_text" [ -n "${node_count:-}" ] && echo "🔢 节点数量:$node_count" + case "$(install_mixed_port_bind_failure_kind 2>/dev/null || true)" in + bind_denied) + echo "🚫 安装后验证:代理端口绑定被系统拒绝(非端口冲突)" + echo "📌 这通常是环境限制,修改端口通常无法解决" + install_mixed_port_bind_observation_line 2>/dev/null || true + echo "👉 下一步:clashctl doctor" + echo "👉 日志:clashctl logs mihomo" + ;; + address_in_use) + : + ;; + esac + if [ -f "$clashctl_file" ]; then CLASH_UI_BOX_ONLY=1 bash "$clashctl_file" ui || true fi diff --git a/scripts/init/script.sh b/scripts/init/script.sh index 028ed7b..caa981e 100644 --- a/scripts/init/script.sh +++ b/scripts/init/script.sh @@ -312,6 +312,7 @@ post_install_verify() { local has_subscription="false" local runtime_ready="false" local controller_ready="false" + local bind_failure_kind="" bind_failure_port="" if clashctl_command_available; then write_runtime_value "INSTALL_VERIFY_COMMAND_READY" "true" @@ -348,10 +349,23 @@ post_install_verify() { runtime_ready="$(install_verify_runtime_ready 2>/dev/null || true)" controller_ready="$(install_verify_controller_ready 2>/dev/null || true)" + bind_failure_kind="$(install_mixed_port_bind_failure_kind 2>/dev/null || true)" + bind_failure_port="$(install_mixed_port_bind_failure_port 2>/dev/null || true)" + + if [ "${has_subscription:-false}" = "true" ] && [ "${bind_failure_kind:-}" = "bind_denied" ]; then + echo + echo "🚫 安装后验证发现:代理端口 ${bind_failure_port:-unknown} 绑定被系统拒绝(非端口冲突)" + echo "📌 修改端口通常无法解决;install 阶段不会通过自动换端口处理该问题" + install_mixed_port_bind_observation_line 2>/dev/null || true + echo "👉 下一步:clashctl doctor" + echo "👉 日志:clashctl logs mihomo" + echo + fi if [ "$has_subscription" = "true" ] \ && [ "${runtime_ready:-false}" = "true" ] \ - && [ "${controller_ready:-false}" = "true" ]; then + && [ "${controller_ready:-false}" = "true" ] \ + && [ "${bind_failure_kind:-}" != "bind_denied" ]; then write_runtime_event_value "RUNTIME_LAST_INSTALL_READY" "true" else write_runtime_event_value "RUNTIME_LAST_INSTALL_READY" "false"