fix: degrade clashon when system proxy is not writable

This commit is contained in:
Arvin
2026-04-13 23:50:25 +08:00
parent 2eecb201b2
commit 7ca7a8cf50
3 changed files with 94 additions and 9 deletions
+58 -3
View File
@@ -46,6 +46,14 @@ _clash_alias_state_file() {
echo "$(_clash_alias_project_dir)/runtime/shell-proxy.env"
}
_clash_alias_runtime_config_file() {
echo "$(_clash_alias_project_dir)/runtime/config.yaml"
}
_clash_alias_yq_bin() {
echo "$(_clash_alias_project_dir)/runtime/bin/yq"
}
_clash_alias_set_persist_enabled() {
local enabled="$1"
local state_file
@@ -72,6 +80,11 @@ _clash_alias_print_sep() {
}
_clash_alias_proxy_on() {
_clashctl_real proxy on >/dev/null || return $?
_clash_alias_export_proxy || return $?
}
_clash_alias_proxy_on_system() {
_clashctl_real proxy on >/dev/null || return $?
_clash_alias_export_system_proxy || return $?
}
@@ -102,6 +115,44 @@ _clash_alias_export_system_proxy() {
[ -n "${all_url:-}" ] || all_url="${http_url/http:\/\//socks5://}"
[ -n "${no_proxy:-}" ] || no_proxy="127.0.0.1,localhost,::1"
_clash_alias_export_proxy_values "$http_url" "$https_url" "$all_url" "$no_proxy"
}
_clash_alias_runtime_proxy_port() {
local config_file yq_bin port
config_file="$(_clash_alias_runtime_config_file)"
[ -s "$config_file" ] || return 1
yq_bin="$(_clash_alias_yq_bin)"
if [ -x "$yq_bin" ]; then
port="$("$yq_bin" eval '.["mixed-port"] // .port // ""' "$config_file" 2>/dev/null | head -n 1)"
else
port="$(sed -nE 's/^[[:space:]]*(mixed-port|port):[[:space:]]*"?([0-9]+)"?[[:space:]]*$/\2/p' "$config_file" | head -n 1)"
fi
[ -n "${port:-}" ] && [ "$port" != "null" ] || return 1
echo "$port"
}
_clash_alias_export_runtime_proxy() {
local port host http_url all_url no_proxy
port="$(_clash_alias_runtime_proxy_port)" || return $?
host="${CLASH_PROXY_HOST:-127.0.0.1}"
http_url="http://${host}:${port}"
all_url="socks5://${host}:${port}"
no_proxy="${NO_PROXY_DEFAULT:-127.0.0.1,localhost,::1}"
_clash_alias_export_proxy_values "$http_url" "$http_url" "$all_url" "$no_proxy"
}
_clash_alias_export_proxy_values() {
local http_url="$1"
local https_url="$2"
local all_url="$3"
local no_proxy="$4"
export http_proxy="$http_url"
export https_proxy="$https_url"
export HTTP_PROXY="$http_url"
@@ -112,6 +163,10 @@ _clash_alias_export_system_proxy() {
export NO_PROXY="$no_proxy"
}
_clash_alias_export_proxy() {
_clash_alias_export_system_proxy || _clash_alias_export_runtime_proxy
}
_clash_alias_unset_shell_proxy() {
unset \
http_proxy https_proxy HTTP_PROXY HTTPS_PROXY \
@@ -131,7 +186,7 @@ _clash_alias_prepare_on() {
_clash_alias_after_on() {
_clash_alias_set_persist_enabled "true"
_clash_alias_export_system_proxy || return $?
_clash_alias_export_proxy || return $?
}
_clash_alias_run_on() {
@@ -165,7 +220,7 @@ _clash_alias_run_on() {
if [ -s "$on_output" ]; then
sed 's/^/ /' "$on_output" >&2
fi
elif _clash_alias_proxy_on; then
elif _clash_alias_proxy_on_system; then
echo "🚨 clashctl on 返回非 0,已通过 proxy on 继续同步当前 Shell(底层返回码:$on_rc)" >&2
if [ -s "$on_output" ]; then
sed 's/^/ /' "$on_output" >&2
@@ -201,7 +256,7 @@ _clash_alias_run_off() {
_clash_alias_auto_restore_proxy() {
_clash_alias_persist_enabled || return 0
_clash_alias_export_system_proxy || return 0
_clash_alias_export_proxy || return 0
echo "♻️ 已恢复当前 shell 代理环境(来自持久化状态)"
return 0
+34 -6
View File
@@ -213,6 +213,7 @@ print_on_feedback() {
cmd_on() {
local relay_switch
local relay_switch_file relay_err_file relay_rc
local system_proxy_rc system_proxy_degraded="false"
local already_on="false"
trap 'rc=$?; ui_error "开启代理失败:cmd_on 在第 ${LINENO} 行执行失败:${BASH_COMMAND}(返回码:${rc})"; ui_next "clashctl logs service"; exit "$rc"' ERR
@@ -260,16 +261,32 @@ cmd_on() {
rm -f "$relay_switch_file" 2>/dev/null || true
fi
if ! system_proxy_enable; then
service_stop >/dev/null 2>&1 || true
die_state "当前环境不支持系统代理接管(仅支持可写 /etc/environment)" "clashctl doctor"
if system_proxy_enable; then
system_proxy_degraded="false"
else
system_proxy_rc=$?
system_proxy_degraded="true"
write_runtime_value "RUNTIME_BOOT_PROXY_KEEP" "false" 2>/dev/null || true
if [ "$system_proxy_rc" -eq 2 ]; then
ui_warn "当前环境不支持系统代理持久接管,仅当前 Shell 生效"
ui_next "开机代理保持不可用;如需持久接管,请使用可写的 $(system_proxy_env_file)"
else
ui_warn "系统代理持久接管写入失败,仅当前 Shell 生效"
ui_next "clashctl doctor"
fi
ui_blank
fi
load_system_state
print_on_feedback
if [ "${CLASH_ALIAS_CALL:-0}" != "1" ]; then
ui_warn "当前通过 clashctl 子进程执行,已开启系统代理,但不会修改当前 Shell 代理变量"
if [ "$system_proxy_degraded" = "true" ]; then
ui_warn "当前通过 clashctl 子进程执行,不能修改当前 Shell 代理变量"
else
ui_warn "当前通过 clashctl 子进程执行,已开启系统代理,但不会修改当前 Shell 代理变量"
fi
ui_next "需要当前 Shell 立即生效:source shell 入口后执行 clashon,或重新打开终端"
ui_blank
fi
@@ -285,11 +302,22 @@ cmd_on() {
}
cmd_off() {
local system_proxy_rc
prepare
service_stop
if ! system_proxy_disable; then
die_state "当前环境不支持系统代理关闭(仅支持可写 /etc/environment)" "clashctl doctor"
if system_proxy_disable; then
:
else
system_proxy_rc=$?
write_runtime_value "RUNTIME_BOOT_PROXY_KEEP" "false" 2>/dev/null || true
if [ "$system_proxy_rc" -eq 2 ]; then
ui_warn "当前环境不支持清理系统代理持久块,已继续关闭运行时"
else
ui_warn "系统代理持久块清理失败,已继续关闭运行时"
ui_next "clashctl doctor"
fi
fi
ui_blank
echo "🧹 系统代理已关闭"