rectification

This commit is contained in:
Arvin
2026-03-20 21:05:58 +08:00
parent 0bd74ee2ed
commit eebfe77a18
11 changed files with 228 additions and 55 deletions

129
clashctl
View File

@ -263,6 +263,13 @@ cmd_update() {
cmd_status() {
local mode running="no"
local service_active="" service_enabled=""
local pid=""
local controller dashboard_url
local config_source generate_status generate_reason generate_at
local run_status run_mode run_pid run_at
local http_port dashboard_port
local secret_exists="no"
mode="$(detect_mode)"
@ -271,46 +278,132 @@ cmd_status() {
if systemctl is-active --quiet "$SERVICE_NAME"; then
running="yes"
fi
service_active="$(systemctl is-active "$SERVICE_NAME" 2>/dev/null || true)"
service_enabled="$(systemctl is-enabled "$SERVICE_NAME" 2>/dev/null || true)"
;;
systemd-installed)
running="no"
service_active="$(systemctl is-active "$SERVICE_NAME" 2>/dev/null || true)"
service_enabled="$(systemctl is-enabled "$SERVICE_NAME" 2>/dev/null || true)"
;;
script)
if is_script_running; then
running="yes"
fi
pid="$(read_pid 2>/dev/null || true)"
;;
none)
running="no"
;;
esac
generate_status="$(read_state_value LAST_GENERATE_STATUS || true)"
generate_reason="$(read_state_value LAST_GENERATE_REASON || true)"
config_source="$(read_state_value LAST_CONFIG_SOURCE || true)"
generate_at="$(read_state_value LAST_GENERATE_AT || true)"
run_status="$(read_state_value LAST_RUN_STATUS || true)"
run_mode="$(read_state_value LAST_RUN_MODE || true)"
run_pid="$(read_state_value LAST_RUN_PID || true)"
run_at="$(read_state_value LAST_RUN_AT || true)"
controller="$(read_runtime_config_value "external-controller" || true)"
dashboard_url="$(cmd_ui --raw 2>/dev/null || true)"
http_port="$(http_port_from_config)"
dashboard_port="$(port_from_controller)"
if [ -n "$(read_runtime_config_value "secret" || true)" ]; then
secret_exists="yes"
fi
echo "=== Clash Status ==="
echo "Project : $PROJECT_DIR"
echo "Mode : $mode"
echo "Running : $running"
echo "Config : $RUNTIME_CONFIG"
if [ "$mode" = "systemd" ] && service_unit_exists; then
echo "Service : installed"
echo "Active : $(systemctl is-active "$SERVICE_NAME" 2>/dev/null || true)"
echo "Enabled : $(systemctl is-enabled "$SERVICE_NAME" 2>/dev/null || true)"
fi
if [ "$mode" = "script" ]; then
local pid
pid="$(read_pid 2>/dev/null || true)"
echo "PID : ${pid:-unknown}"
if [ -f "$RUNTIME_CONFIG" ]; then
echo "ConfigExists : yes"
else
echo "ConfigExists : no"
fi
if [ -f "$STATE_FILE" ]; then
echo "LastStatus : $(read_state_value LAST_GENERATE_STATUS || true)"
echo "LastReason : $(read_state_value LAST_GENERATE_REASON || true)"
echo "LastSource : $(read_state_value LAST_CONFIG_SOURCE || true)"
echo "LastAt : $(read_state_value LAST_GENERATE_AT || true)"
echo "StateFile : $STATE_FILE"
else
echo "StateFile : missing"
fi
local controller
controller="$(read_runtime_config_value "external-controller" || true)"
if [ -n "${controller:-}" ]; then
echo "Dashboard : $(cmd_ui --raw)"
case "$mode" in
systemd|systemd-installed)
echo "Service : installed"
echo "Active : ${service_active:-unknown}"
echo "Enabled : ${service_enabled:-unknown}"
;;
script)
echo "Service : script"
echo "PID : ${pid:-unknown}"
;;
none)
echo "Service : none"
;;
esac
echo "Generate : ${generate_status:-unknown}"
if [ -n "${generate_reason:-}" ]; then
echo "GenReason : $generate_reason"
fi
if [ -n "${config_source:-}" ]; then
echo "ConfigSource : $config_source"
fi
if [ -n "${generate_at:-}" ]; then
echo "GeneratedAt : $generate_at"
fi
if [ -n "${run_status:-}" ]; then
echo "RunStatus : $run_status"
fi
if [ -n "${run_mode:-}" ]; then
echo "RunMode : $run_mode"
fi
if [ -n "${run_pid:-}" ]; then
echo "RunPID : $run_pid"
fi
if [ -n "${run_at:-}" ]; then
echo "RunAt : $run_at"
fi
echo "ProxyPort : $http_port"
echo "DashPort : $dashboard_port"
if [ -n "${controller:-}" ]; then
echo "Controller : $controller"
else
echo "Controller : 127.0.0.1:9090 (fallback)"
fi
if [ -n "${dashboard_url:-}" ]; then
echo "Dashboard : $dashboard_url"
fi
echo "Secret : $secret_exists"
echo
case "$running" in
yes)
ok "status summary: running"
;;
no)
if [ "$mode" = "systemd-installed" ]; then
warn "status summary: installed but not running"
else
warn "status summary: not running"
fi
;;
*)
warn "status summary: unknown"
;;
esac
}
doctor_ok() {

BIN
config/Country.mmdb Normal file

Binary file not shown.

9
config/mixin.d/README.md Normal file
View File

@ -0,0 +1,9 @@
# Mixin 配置目录
将额外的 Clash YAML 配置放在此目录下,脚本会按文件名排序后依次拼接到生成的 `config.yaml` 末尾。
如需手动指定顺序或使用自定义路径,请在 `.env` 中设置:
```bash
export CLASH_MIXIN_PATHS='conf/mixin.d/base.yaml,conf/mixin.d/rules.yaml'
```

31
config/templete.yaml Normal file
View File

@ -0,0 +1,31 @@
# HTTP 代理端口
port: CLASH_HTTP_PORT_PLACEHOLDER
# SOCKS5 代理端口
socks-port: CLASH_SOCKS_PORT_PLACEHOLDER
# Linux 和 macOS 的 redir 代理端口
redir-port: CLASH_REDIR_PORT_PLACEHOLDER
# 监听IP地址
bind-address: CLASH_LISTEN_IP_PLACEHOLDER
# 允许局域网的连接
allow-lan: CLASH_ALLOW_LAN_PLACEHOLDER
# 规则模式Rule规则 / Global全局代理/ Direct全局直连
mode: rule
# 设置日志输出级别 (默认级别silent即不输出任何内容以避免因日志内容过大而导致程序内存溢出
# 5 个级别silent / info / warning / error / debug。级别越高日志输出量越大越倾向于调试若需要请自行开启。
log-level: silent
# Clash 的 RESTful API
external-controller: 'EXTERNAL_CONTROLLER_PLACEHOLDER'
# RESTful API 的口令
secret: 'b&ZlKTte5OnEt2Sn'
# 您可以将静态网页资源(如 clash-dashboard放置在一个目录中clash 将会服务于 `RESTful API/ui`
# 参数应填写配置目录的相对路径或绝对路径。
# external-ui: /code/clash-dashboard

View File

@ -470,7 +470,10 @@ if [ -f "$Install_Dir/clashoff" ]; then
fi
# =========================
# 友好收尾输出(闭环)
# 友好收尾输出
# - 不再强调瞬时 active / inactive
# - 统一引导到 clashctl
# - 兼容 systemd / 非 systemd
# =========================
section "安装完成"
@ -478,28 +481,37 @@ ok "Clash for Linux 已安装至: $(path "${Install_Dir}")"
log "📦 安装目录:$(path "${Install_Dir}")"
log "👤 运行用户:${Service_User}:${Service_Group}"
log "🔧 服务名称:${Service_Name}.service"
log "🧩 管理入口:$(cmd "clashctl")"
if command -v systemctl >/dev/null 2>&1; then
section "服务状态"
se="${Service_Enabled:-unknown}"
ss="${Service_Started:-unknown}"
[[ "$se" == "enabled" ]] && se_colored="$(good "$se")" || se_colored="$(bad "$se")"
[[ "$ss" == "active" ]] && ss_colored="$(good "$ss")" || ss_colored="$(bad "$ss")"
log "🧷 开机自启:${se_colored}"
log "🟢 服务状态:${ss_colored}"
log ""
log "${C_BOLD}常用命令:${C_NC}"
log " $(cmd "systemctl status ${Service_Name}.service")"
log " $(cmd "systemctl restart ${Service_Name}.service")"
log "🔧 服务名称:${Service_Name}.service"
else
log "🔧 运行模式:非 systemd 环境(将使用脚本模式兜底)"
fi
# =========================
# Dashboard / Secret
# 安装结果
# 不在这里渲染瞬时运行态,避免误导
# =========================
section "安装结果"
ok "核心文件已就位"
ok "运行入口已收敛为 clashctl"
if [[ -x "/usr/local/bin/clashctl" ]]; then
ok "命令已可用:$(cmd "clashctl")"
else
warn "未检测到 /usr/local/bin/clashctl请确认安装脚本是否已完成链接"
fi
log ""
log "${C_BOLD}推荐下一步:${C_NC}"
log " 1. $(cmd "clashctl generate") # 生成运行配置"
log " 2. $(cmd "clashctl start") # 启动 Clash"
log " 3. $(cmd "clashctl doctor") # 健康检查"
# =========================
# 控制面板 / Secret
# =========================
section "控制面板"
@ -534,16 +546,24 @@ fi
CONF_DIR="$Install_Dir/conf"
TEMP_DIR="$Install_Dir/temp"
RUNTIME_DIR="$Install_Dir/runtime"
SECRET_VAL=""
SECRET_FILE=""
read_secret_safe() {
local f="$1"
[[ -f "$f" ]] || return 1
read_secret_from_config "$f" 2>/dev/null || true
}
for _ in {1..15}; do
for f in \
"$RUNTIME_DIR/config.yaml" \
"$TEMP_DIR/config.yaml" \
"$CONF_DIR/config.yaml"
do
SECRET_VAL="$(read_secret_from_config "$f" 2>/dev/null || true)"
SECRET_VAL="$(read_secret_safe "$f")"
if [[ -n "$SECRET_VAL" ]]; then
SECRET_FILE="$f"
break 2
@ -555,16 +575,14 @@ done
dash="http://${api_host}:${api_port}/ui"
log "🌐 Dashboard$(url "$dash")"
SHOW_FILE="${SECRET_FILE:-$CONF_DIR/config.yaml}"
SHOW_FILE="${SECRET_FILE:-$RUNTIME_DIR/config.yaml}"
if [[ -n "$SECRET_VAL" ]]; then
MASKED="${SECRET_VAL}"
log "🔐 Secret${C_YELLOW}${MASKED}${C_NC}"
# log " 查看完整 Secret$(cmd "sed -nE 's/^[[:space:]]*secret:[[:space:]]*//p' \"$SHOW_FILE\" | head -n 1")"
log "🔐 Secret${C_YELLOW}${SECRET_VAL}${C_NC}"
else
log "🔐 Secret${C_YELLOW}启动中暂未读到(稍后再试)${C_NC}"
log " 稍后查看:$(cmd "sed -nE 's/^[[:space:]]*secret:[[:space:]]*//p' \"$CONF_DIR/config.yaml\" | head -n 1")"
log " 也可检查运行态$(cmd "sed -nE 's/^[[:space:]]*secret:[[:space:]]*//p' \"$TEMP_DIR/config.yaml\" | head -n 1")"
log "🔐 Secret${C_YELLOW}暂未读取到${C_NC}"
log " 启动后可查看:$(cmd "sed -nE 's/^[[:space:]]*secret:[[:space:]]*//p' \"$RUNTIME_DIR/config.yaml\" | head -n 1")"
log " 或检查旧路径$(cmd "sed -nE 's/^[[:space:]]*secret:[[:space:]]*//p' \"$TEMP_DIR/config.yaml\" | head -n 1")"
fi
# =========================
@ -580,20 +598,41 @@ else
warn "订阅地址未配置(必须)"
log ""
log "配置订阅地址:"
log " $(cmd "bash -c 'echo \"CLASH_URL=<订阅地址>\" > ${ENV_FILE}'")"
log " $(cmd "bash -c 'printf \"%s\n\" \"CLASH_URL=<订阅地址>\" > \"${ENV_FILE}\"'")"
log ""
log "配置完成后重启服务"
log " $(cmd "systemctl restart ${Service_Name}.service")"
log "配置完成后执行"
log " 1. $(cmd "clashctl generate")"
log " 2. $(cmd "clashctl start")"
log " 3. $(cmd "clashctl doctor")"
fi
# =========================
# 下一步
# 常用命令(统一只教 clashctl
# =========================
section "下一步开启代理(可选)"
section "常用命令"
log " $(cmd "clashctl status") # 查看运行状态"
log " $(cmd "clashctl logs") # 查看最近日志"
log " $(cmd "clashctl logs -f") # 持续追踪日志"
log " $(cmd "clashctl stop") # 停止 Clash"
log " $(cmd "clashctl restart") # 重启 Clash"
log " $(cmd "clashctl doctor") # 健康检查"
# =========================
# 终端代理(可选)
# =========================
section "终端代理(可选)"
log " $(cmd "clashctl on") # 开启当前终端代理"
log " $(cmd "clashctl off") # 关闭当前终端代理"
log " $(cmd "clashctl status") # 查看状态"
# =========================
# 旧入口收敛提示
# =========================
section "说明"
log "旧脚本已收敛,请优先使用:$(cmd "clashctl")"
log "不建议继续直接操作 restart.sh / update.sh / 手写 systemctl 命令"
# =========================
# 启动后快速诊断
@ -602,6 +641,7 @@ sleep 1
if command -v journalctl >/dev/null 2>&1; then
if journalctl -u "${Service_Name}.service" -n 50 --no-pager 2>/dev/null \
| grep -q "Clash订阅地址不可访问"; then
warn "服务启动异常:订阅不可用,请检查 CLASH_URL可能过期 / 404 / 被墙)"
warn "检测到启动异常:订阅不可用,请检查 CLASH_URL可能过期 / 404 / 被墙)"
log "建议执行:$(cmd "clashctl doctor")"
fi
fi

0
logs/clash.log Normal file
View File

0
runtime/clash.pid Normal file
View File

0
runtime/proxy.env Normal file
View File

0
runtime/state.env Normal file
View File

0
scripts/doctor.sh Normal file
View File

0
scripts/logs.sh Normal file
View File