mirror of
https://github.com/wnlen/clash-for-linux.git
synced 2026-10-10 20:23:04 +08:00
Merge pull request #175 from wnlen/codex/establish-codex-bootstrap-document-fej638
System-wide proxy management, auto-relay selection, config cleanup, and Codex bootstrap docs
This commit is contained in:
+5
-16
@@ -45,11 +45,11 @@ _clash_alias_print_sep() {
|
||||
}
|
||||
|
||||
_clash_alias_proxy_on() {
|
||||
eval "$(_clashctl_real proxy on)" || return $?
|
||||
_clashctl_real proxy on >/dev/null || return $?
|
||||
}
|
||||
|
||||
_clash_alias_proxy_off() {
|
||||
eval "$(_clashctl_real proxy off)" || true
|
||||
_clashctl_real proxy off >/dev/null || true
|
||||
}
|
||||
|
||||
_clash_alias_proxy_show() {
|
||||
@@ -85,13 +85,7 @@ _clash_alias_after_on() {
|
||||
_clash_alias_after_off() {
|
||||
_clash_alias_set_persist_enabled "false"
|
||||
_clash_alias_print_sep
|
||||
echo "🔴 已关闭代理环境"
|
||||
echo "🧹 当前 Shell 代理变量已清理"
|
||||
if [ "${CLASH_WRAPPER_EXEC:-0}" = "1" ]; then
|
||||
echo '💡 若当前终端仍有代理变量,请执行:eval "$(clashctl proxy off)"'
|
||||
fi
|
||||
echo "🧭 新终端默认代理:已关闭"
|
||||
echo "👉 下一步:clashctl status"
|
||||
echo "🧹 系统代理已关闭"
|
||||
}
|
||||
|
||||
_clash_alias_run_on() {
|
||||
@@ -110,12 +104,7 @@ _clash_alias_run_off() {
|
||||
}
|
||||
|
||||
_clash_alias_auto_restore_proxy() {
|
||||
[ "${CLASH_FOR_LINUX_PROXY_AUTO_RESTORED:-0}" = "1" ] && return 0
|
||||
export CLASH_FOR_LINUX_PROXY_AUTO_RESTORED="1"
|
||||
|
||||
if _clash_alias_persist_enabled; then
|
||||
_clash_alias_proxy_on >/dev/null 2>&1 || true
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
clashctl() {
|
||||
@@ -138,7 +127,7 @@ clashctl() {
|
||||
off)
|
||||
_clash_alias_proxy_off
|
||||
_clash_alias_print_sep
|
||||
echo "🧹 当前 Shell 代理变量已清理"
|
||||
echo "🧹 系统代理已关闭"
|
||||
;;
|
||||
*)
|
||||
_clashctl_real "$@"
|
||||
|
||||
+64
-69
@@ -260,6 +260,11 @@ cmd_on() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! system_proxy_enable; then
|
||||
service_stop >/dev/null 2>&1 || true
|
||||
die_state "当前环境不支持系统代理接管(仅支持可写 /etc/environment)" "clashctl proxy show"
|
||||
fi
|
||||
|
||||
load_system_state
|
||||
print_on_feedback
|
||||
|
||||
@@ -274,9 +279,11 @@ cmd_off() {
|
||||
prepare
|
||||
service_stop
|
||||
|
||||
ui_title "🔴 代理环境已关闭"
|
||||
ui_info "当前 Shell 代理变量已清理(函数系统已生效)"
|
||||
ui_next "clashctl status"
|
||||
if ! system_proxy_disable; then
|
||||
die_state "当前环境不支持系统代理关闭(仅支持可写 /etc/environment)" "clashctl proxy show"
|
||||
fi
|
||||
|
||||
echo "🧹 系统代理已关闭"
|
||||
ui_blank
|
||||
}
|
||||
|
||||
@@ -1432,39 +1439,12 @@ status_current_proxy_brief() {
|
||||
echo "暂无可切换策略组"
|
||||
}
|
||||
|
||||
shell_proxy_enabled() {
|
||||
[ -n "${http_proxy:-}" ] \
|
||||
|| [ -n "${https_proxy:-}" ] \
|
||||
|| [ -n "${HTTP_PROXY:-}" ] \
|
||||
|| [ -n "${HTTPS_PROXY:-}" ] \
|
||||
|| [ -n "${all_proxy:-}" ] \
|
||||
|| [ -n "${ALL_PROXY:-}" ]
|
||||
}
|
||||
|
||||
shell_proxy_http_value() {
|
||||
if [ -n "${http_proxy:-}" ]; then
|
||||
echo "$http_proxy"
|
||||
return 0
|
||||
system_proxy_supported_state() {
|
||||
if system_proxy_supported; then
|
||||
echo "true"
|
||||
else
|
||||
echo "false"
|
||||
fi
|
||||
|
||||
if [ -n "${HTTP_PROXY:-}" ]; then
|
||||
echo "$HTTP_PROXY"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
shell_proxy_matches_runtime() {
|
||||
local expected actual
|
||||
|
||||
expected="$(proxy_http_url 2>/dev/null || true)"
|
||||
actual="$(shell_proxy_http_value)"
|
||||
|
||||
[ -n "${expected:-}" ] || return 1
|
||||
[ -n "${actual:-}" ] || return 1
|
||||
|
||||
[ "$expected" = "$actual" ]
|
||||
}
|
||||
|
||||
connectivity_issue_code() {
|
||||
@@ -1504,13 +1484,18 @@ connectivity_issue_code() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! shell_proxy_enabled; then
|
||||
echo "shell_proxy_missing"
|
||||
if ! system_proxy_supported; then
|
||||
echo "system_proxy_unsupported"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! shell_proxy_matches_runtime; then
|
||||
echo "shell_proxy_mismatch"
|
||||
if [ "$(system_proxy_status 2>/dev/null || echo off)" != "on" ]; then
|
||||
echo "system_proxy_off"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! system_proxy_matches_runtime; then
|
||||
echo "system_proxy_mismatch"
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -1525,8 +1510,9 @@ connectivity_issue_text() {
|
||||
config_invalid) echo "异常(当前运行配置不可用)" ;;
|
||||
subscription_unhealthy) echo "异常(当前主订阅不可用)" ;;
|
||||
proxy_control_broken) echo "异常(当前无可用策略组或节点控制面异常)" ;;
|
||||
shell_proxy_missing) echo "未接管(当前 Shell 未注入代理环境)" ;;
|
||||
shell_proxy_mismatch) echo "异常(当前 Shell 代理与运行时端口不一致)" ;;
|
||||
system_proxy_unsupported) echo "未接管(当前环境不支持系统代理)" ;;
|
||||
system_proxy_off) echo "未接管(系统代理未开启)" ;;
|
||||
system_proxy_mismatch) echo "异常(系统代理端口与运行时不一致)" ;;
|
||||
*) echo "未知" ;;
|
||||
esac
|
||||
}
|
||||
@@ -1551,11 +1537,14 @@ connectivity_next_action() {
|
||||
proxy_control_broken)
|
||||
echo "clashctl status --verbose"
|
||||
;;
|
||||
shell_proxy_missing)
|
||||
echo 'eval "$(clashctl proxy on)"'
|
||||
system_proxy_unsupported)
|
||||
echo "clashctl doctor"
|
||||
;;
|
||||
shell_proxy_mismatch)
|
||||
echo 'eval "$(clashctl proxy off)" && eval "$(clashctl proxy on)"'
|
||||
system_proxy_off)
|
||||
echo "clashctl proxy on"
|
||||
;;
|
||||
system_proxy_mismatch)
|
||||
echo "clashctl proxy off && clashctl proxy on"
|
||||
;;
|
||||
*)
|
||||
echo "clashctl doctor"
|
||||
@@ -1566,6 +1555,7 @@ connectivity_next_action() {
|
||||
connectivity_evidence_lines() {
|
||||
local runtime_running controller_ok build_status subscription_status
|
||||
local group_count expected_proxy actual_proxy active config_source
|
||||
local system_proxy_state system_proxy_supported_text
|
||||
|
||||
if status_is_running; then
|
||||
runtime_running="true"
|
||||
@@ -1585,7 +1575,9 @@ connectivity_evidence_lines() {
|
||||
active="$(active_subscription_name 2>/dev/null || true)"
|
||||
config_source="$(status_runtime_config_source 2>/dev/null || true)"
|
||||
expected_proxy="$(proxy_http_url 2>/dev/null || true)"
|
||||
actual_proxy="$(shell_proxy_http_value)"
|
||||
actual_proxy="$(system_proxy_http_value 2>/dev/null || true)"
|
||||
system_proxy_state="$(system_proxy_status 2>/dev/null || echo off)"
|
||||
system_proxy_supported_text="$(system_proxy_supported_state)"
|
||||
|
||||
echo "• runtime_running = ${runtime_running:-false}"
|
||||
echo "• controller_reachable = ${controller_ok:-false}"
|
||||
@@ -1595,12 +1587,9 @@ connectivity_evidence_lines() {
|
||||
echo "• config_source = ${config_source:-unknown}"
|
||||
echo "• proxy_group_count = ${group_count:-0}"
|
||||
|
||||
if shell_proxy_enabled; then
|
||||
echo "• shell_proxy_enabled = true"
|
||||
echo "• shell_proxy_http = ${actual_proxy:-unknown}"
|
||||
else
|
||||
echo "• shell_proxy_enabled = false"
|
||||
fi
|
||||
echo "• system_proxy_supported = ${system_proxy_supported_text:-false}"
|
||||
echo "• system_proxy_enabled = ${system_proxy_state:-off}"
|
||||
[ -n "${actual_proxy:-}" ] && echo "• system_proxy_http = ${actual_proxy}"
|
||||
|
||||
if [ -n "${expected_proxy:-}" ]; then
|
||||
echo "• runtime_proxy_http = $expected_proxy"
|
||||
@@ -1758,10 +1747,10 @@ print_status_summary_compact() {
|
||||
user_risk="$(status_user_risk_text)"
|
||||
current_proxy_brief="$(status_current_proxy_brief)"
|
||||
next_action="$(system_state_default_action 2>/dev/null || echo 'clashctl status')"
|
||||
if shell_proxy_persist_enabled 2>/dev/null; then
|
||||
shell_persist_text="开启"
|
||||
if system_proxy_supported; then
|
||||
shell_persist_text="$(system_proxy_status 2>/dev/null || echo off)"
|
||||
else
|
||||
shell_persist_text="关闭"
|
||||
shell_persist_text="unsupported"
|
||||
fi
|
||||
if [ -f "$(runtime_dashboard_dir)/index.html" ]; then
|
||||
dashboard_text="已部署"
|
||||
@@ -1802,7 +1791,7 @@ print_status_summary_compact() {
|
||||
echo "⚙️ 运行后端:$(status_runtime_backend_text)"
|
||||
echo "🧪 环境模式:$(status_container_mode_text)"
|
||||
echo "🧪 Tun 状态:${tun_text:-未知}"
|
||||
echo "🧭 新终端代理继承:${shell_persist_text}"
|
||||
echo "🧭 系统代理状态:${shell_persist_text}"
|
||||
echo "🧩 Dashboard:${dashboard_text}(来源:${dashboard_source_text})"
|
||||
echo "🧩 Dashboard 策略:${dashboard_policy_text}"
|
||||
echo "🔐 控制器密钥:${secret_text}"
|
||||
@@ -1904,10 +1893,10 @@ print_status_summary_verbose() {
|
||||
tun_verify_result="$(status_tun_last_verify_result 2>/dev/null || true)"
|
||||
tun_verify_reason="$(status_tun_last_verify_reason 2>/dev/null || true)"
|
||||
tun_verify_time="$(status_tun_last_verify_time 2>/dev/null || true)"
|
||||
if shell_proxy_persist_enabled 2>/dev/null; then
|
||||
shell_persist_text="开启"
|
||||
if system_proxy_supported; then
|
||||
shell_persist_text="$(system_proxy_status 2>/dev/null || echo off)"
|
||||
else
|
||||
shell_persist_text="关闭"
|
||||
shell_persist_text="unsupported"
|
||||
fi
|
||||
if [ -f "$(runtime_dashboard_dir)/index.html" ]; then
|
||||
dashboard_text="已部署"
|
||||
@@ -1970,7 +1959,7 @@ print_status_summary_verbose() {
|
||||
echo "🧪 环境模式:${install_container_text:-unknown}"
|
||||
echo "🧩 安装验证:${install_verify_text:-unknown}"
|
||||
echo "🧭 端口裁决:${port_adjustment_text:-unknown}"
|
||||
echo "🧭 新终端代理继承:${shell_persist_text}"
|
||||
echo "🧭 系统代理状态:${shell_persist_text}"
|
||||
echo "🧩 Dashboard:${dashboard_text}(来源:${dashboard_source_text})"
|
||||
echo "🧩 Dashboard 策略:${dashboard_policy_text}"
|
||||
echo "🔐 控制器密钥:${secret_text}"
|
||||
@@ -2837,10 +2826,10 @@ doctor_runtime_events() {
|
||||
build_applied="$(status_runtime_build_applied 2>/dev/null || true)"
|
||||
build_applied_time="$(status_runtime_build_applied_time 2>/dev/null || true)"
|
||||
build_applied_reason="$(status_runtime_build_applied_reason 2>/dev/null || true)"
|
||||
if shell_proxy_persist_enabled 2>/dev/null; then
|
||||
shell_persist_text="开启"
|
||||
if system_proxy_supported; then
|
||||
shell_persist_text="$(system_proxy_status 2>/dev/null || echo off)"
|
||||
else
|
||||
shell_persist_text="关闭"
|
||||
shell_persist_text="unsupported"
|
||||
fi
|
||||
if [ -f "$(runtime_dashboard_dir)/index.html" ]; then
|
||||
dashboard_status="已部署"
|
||||
@@ -2860,7 +2849,7 @@ doctor_runtime_events() {
|
||||
|
||||
doctor_ok "当前风险等级:${risk_level:-unknown}"
|
||||
doctor_ok "当前配置来源:${config_source:-unknown}"
|
||||
doctor_ok "新终端代理继承:${shell_persist_text}"
|
||||
doctor_ok "系统代理状态:${shell_persist_text}"
|
||||
doctor_ok "Dashboard 运行目录:${dashboard_status}(来源:${dashboard_source})"
|
||||
doctor_ok ".env 控制器密钥:${secret_status}"
|
||||
|
||||
@@ -4809,10 +4798,18 @@ cmd_proxy() {
|
||||
print_proxy_show
|
||||
;;
|
||||
on)
|
||||
print_proxy_on_script
|
||||
if ! system_proxy_enable; then
|
||||
die_state "当前环境不支持系统代理接管(仅支持可写 /etc/environment)" "clashctl proxy show"
|
||||
fi
|
||||
ui_ok "系统代理已开启"
|
||||
print_proxy_show
|
||||
;;
|
||||
off)
|
||||
print_proxy_off_script
|
||||
if ! system_proxy_disable; then
|
||||
die_state "当前环境不支持系统代理关闭(仅支持可写 /etc/environment)" "clashctl proxy show"
|
||||
fi
|
||||
ui_ok "系统代理已关闭"
|
||||
print_proxy_show
|
||||
;;
|
||||
groups)
|
||||
cmd_proxy_groups
|
||||
@@ -4852,7 +4849,7 @@ cmd_proxy() {
|
||||
echo " clashctl proxy select <策略组> <节点>"
|
||||
echo
|
||||
echo "🧩 说明:"
|
||||
echo " on/off 输出当前 Shell 代理变量脚本"
|
||||
echo " on/off 开启或关闭系统代理(/etc/environment)"
|
||||
echo " groups 查看可切换策略组"
|
||||
echo " current 查看当前节点"
|
||||
echo " nodes 查看某策略组候选节点"
|
||||
@@ -4863,8 +4860,6 @@ cmd_proxy() {
|
||||
echo " clashctl proxy groups"
|
||||
echo " clashctl proxy select"
|
||||
echo
|
||||
echo '🌐 注入当前 Shell:eval "$(clashctl proxy on)"'
|
||||
echo '🧹 清理当前 Shell:eval "$(clashctl proxy off)"'
|
||||
echo
|
||||
ui_next "clashctl select"
|
||||
ui_blank
|
||||
|
||||
+119
-33
@@ -31,48 +31,134 @@ proxy_no_proxy_value() {
|
||||
echo "${NO_PROXY_DEFAULT:-127.0.0.1,localhost,::1}"
|
||||
}
|
||||
|
||||
system_proxy_env_file() {
|
||||
echo "${SYSTEM_PROXY_ENV_FILE:-/etc/environment}"
|
||||
}
|
||||
|
||||
system_proxy_block_begin() {
|
||||
echo "# >>> clash-for-linux system proxy >>>"
|
||||
}
|
||||
|
||||
system_proxy_block_end() {
|
||||
echo "# <<< clash-for-linux system proxy <<<"
|
||||
}
|
||||
|
||||
system_proxy_supported() {
|
||||
local file dir
|
||||
|
||||
file="$(system_proxy_env_file)"
|
||||
dir="$(dirname "$file")"
|
||||
|
||||
if [ -f "$file" ]; then
|
||||
[ -w "$file" ]
|
||||
return $?
|
||||
fi
|
||||
|
||||
[ -d "$dir" ] && [ -w "$dir" ]
|
||||
}
|
||||
|
||||
system_proxy_status() {
|
||||
local file
|
||||
file="$(system_proxy_env_file)"
|
||||
|
||||
[ -f "$file" ] || {
|
||||
echo "off"
|
||||
return 0
|
||||
}
|
||||
|
||||
if grep -Fq "$(system_proxy_block_begin)" "$file" 2>/dev/null; then
|
||||
echo "on"
|
||||
else
|
||||
echo "off"
|
||||
fi
|
||||
}
|
||||
|
||||
system_proxy_http_value() {
|
||||
local file value
|
||||
file="$(system_proxy_env_file)"
|
||||
[ -f "$file" ] || return 1
|
||||
|
||||
value="$(sed -nE 's/^http_proxy="?([^"\r\n]+)"?$/\1/p' "$file" | tail -n 1)"
|
||||
[ -n "${value:-}" ] || return 1
|
||||
|
||||
echo "$value"
|
||||
}
|
||||
|
||||
system_proxy_matches_runtime() {
|
||||
local expected actual
|
||||
|
||||
expected="$(proxy_http_url 2>/dev/null || true)"
|
||||
actual="$(system_proxy_http_value 2>/dev/null || true)"
|
||||
|
||||
[ -n "${expected:-}" ] || return 1
|
||||
[ -n "${actual:-}" ] || return 1
|
||||
[ "$expected" = "$actual" ]
|
||||
}
|
||||
|
||||
system_proxy_write_block() {
|
||||
local mode="$1"
|
||||
local file tmp http_url socks_url no_proxy
|
||||
|
||||
file="$(system_proxy_env_file)"
|
||||
tmp="$(mktemp)"
|
||||
|
||||
[ -f "$file" ] && cat "$file" > "$tmp"
|
||||
|
||||
awk -v begin="$(system_proxy_block_begin)" -v end="$(system_proxy_block_end)" '
|
||||
$0 == begin {skip=1; next}
|
||||
$0 == end {skip=0; next}
|
||||
skip != 1 {print}
|
||||
' "$tmp" > "${tmp}.clean"
|
||||
|
||||
mv -f "${tmp}.clean" "$tmp"
|
||||
|
||||
if [ "$mode" = "on" ]; then
|
||||
http_url="$(proxy_http_url)"
|
||||
socks_url="$(proxy_socks_url)"
|
||||
no_proxy="$(proxy_no_proxy_value)"
|
||||
|
||||
{
|
||||
echo "$(system_proxy_block_begin)"
|
||||
echo "http_proxy="$http_url""
|
||||
echo "https_proxy="$http_url""
|
||||
echo "HTTP_PROXY="$http_url""
|
||||
echo "HTTPS_PROXY="$http_url""
|
||||
echo "all_proxy="$socks_url""
|
||||
echo "ALL_PROXY="$socks_url""
|
||||
echo "no_proxy="$no_proxy""
|
||||
echo "NO_PROXY="$no_proxy""
|
||||
echo "$(system_proxy_block_end)"
|
||||
} >> "$tmp"
|
||||
fi
|
||||
|
||||
cat "$tmp" > "$file"
|
||||
rm -f "$tmp" 2>/dev/null || true
|
||||
}
|
||||
|
||||
system_proxy_enable() {
|
||||
system_proxy_supported || return 2
|
||||
system_proxy_write_block "on"
|
||||
}
|
||||
|
||||
system_proxy_disable() {
|
||||
system_proxy_supported || return 2
|
||||
system_proxy_write_block "off"
|
||||
}
|
||||
|
||||
print_proxy_show() {
|
||||
local status
|
||||
status="$(system_proxy_status)"
|
||||
|
||||
echo
|
||||
echo "😼 当前代理环境"
|
||||
echo
|
||||
echo "🌐 HTTP:$(proxy_http_url)"
|
||||
echo "🧦 SOCKS5:$(proxy_socks_url)"
|
||||
echo "🚫 NO_PROXY:$(proxy_no_proxy_value)"
|
||||
echo "🧭 系统代理:${status}($(system_proxy_env_file))"
|
||||
echo
|
||||
}
|
||||
|
||||
print_proxy_on_script() {
|
||||
local http_url socks_url no_proxy
|
||||
|
||||
http_url="$(proxy_http_url)"
|
||||
socks_url="$(proxy_socks_url)"
|
||||
no_proxy="$(proxy_no_proxy_value)"
|
||||
|
||||
cat <<EOF
|
||||
export http_proxy="$http_url"
|
||||
export https_proxy="$http_url"
|
||||
export HTTP_PROXY="$http_url"
|
||||
export HTTPS_PROXY="$http_url"
|
||||
export all_proxy="$socks_url"
|
||||
export ALL_PROXY="$socks_url"
|
||||
export no_proxy="$no_proxy"
|
||||
export NO_PROXY="$no_proxy"
|
||||
EOF
|
||||
}
|
||||
|
||||
print_proxy_off_script() {
|
||||
cat <<'EOF'
|
||||
unset http_proxy
|
||||
unset https_proxy
|
||||
unset HTTP_PROXY
|
||||
unset HTTPS_PROXY
|
||||
unset all_proxy
|
||||
unset ALL_PROXY
|
||||
unset no_proxy
|
||||
unset NO_PROXY
|
||||
EOF
|
||||
}
|
||||
|
||||
controller_addr() {
|
||||
local config_file="${1:-$RUNTIME_DIR/config.yaml}"
|
||||
|
||||
@@ -335,4 +421,4 @@ print_proxy_groups_summary() {
|
||||
echo "$group"
|
||||
fi
|
||||
done < <(proxy_group_list)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user