mirror of
https://github.com/wnlen/clash-for-linux.git
synced 2026-10-10 04:03:04 +08:00
feat: refine install flow, TUN experience, and command UX
This commit is contained in:
@@ -16,7 +16,7 @@ export CLASH_DNS_PORT="1053"
|
|||||||
export CLASH_AUTO_UPDATE_SUBSCRIPTIONS="true"
|
export CLASH_AUTO_UPDATE_SUBSCRIPTIONS="true"
|
||||||
|
|
||||||
# 版本
|
# 版本
|
||||||
export MIHOMO_VERSION="v1.19.21"
|
export MIHOMO_VERSION="v1.19.23"
|
||||||
export CLASH_VERSION="v1.18.0"
|
export CLASH_VERSION="v1.18.0"
|
||||||
export YQ_VERSION="v4.52.4"
|
export YQ_VERSION="v4.52.4"
|
||||||
export SUBCONVERTER_VERSION="v0.9.0"
|
export SUBCONVERTER_VERSION="v0.9.0"
|
||||||
|
|||||||
@@ -1,25 +1,28 @@
|
|||||||
<h1 align="center">
|
<h1 align="center">
|
||||||
🐧 Linux 一键安装 Clash</a>
|
🐱 Linux 一键安装 Clash</a>
|
||||||
<br>
|
<br>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
|
||||||
<h3 align="center">
|
<h3 align="center">
|
||||||
一个面向 Linux 的 Clash(<a href="https://github.com/MetaCubeX/mihomo">Mihomo</a>)管理工具。
|
一个面向 Linux 的 Clash(<a href="https://github.com/MetaCubeX/mihomo">Mihomo</a>)管理工具。
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="docs/assets/5.png" width="100%">
|
<img src="resources/ui.png" width="100%">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
# ✨ 核心特性
|
# ✨ 核心特性
|
||||||
|
|
||||||
- 🚀 **自动识别系统架构**,自动下载并使用对应 Clash 内核
|
- 🚀 **自动识别系统架构:**自动下载并使用对应 Clash 内核
|
||||||
- 🧪 **端口自动检测与分配**,避免冲突
|
- 🧪 **端口自动检测与分配:**避免冲突
|
||||||
- 🔄 **多订阅管理(clashctl)**,支持自动订阅切换
|
- 🔄 **多订阅管理:**可以保存多个订阅,通过 `clashctl use` 切换当前主订阅。
|
||||||
- 🧠 **Mixin 机制**,可按需追加/覆盖 Clash 配置
|
- 💫 **节点选择:**使用编号交互选择策略组和节点。
|
||||||
- 🌐 **Tun 模式支持**(需 Clash Meta / Premium)
|
- 🌐 **Tun 模式:**用于透明代理接管场景。
|
||||||
- 🔐 **安全默认配置**,自动生成或自定义 Secret
|
- 🧠 **Mixin 机制:**可按需追加/覆盖 Clash 配置
|
||||||
- 🩺 **内置诊断工具(`doctor`)**,快速排障
|
- 👤 **不同权限:**兼容 `root` 与普通用户环境。
|
||||||
|
- 🔐 **安全默认配置:**自动生成或自定义 Secret
|
||||||
|
- 🩺 **内置诊断工具(`doctor`):**快速排障
|
||||||
|
|
||||||
### 适用场景
|
### 适用场景
|
||||||
|
|
||||||
@@ -46,28 +49,29 @@ bash install.sh
|
|||||||
## ⌨️ 命令一览
|
## ⌨️ 命令一览
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
用法:
|
〽️ 常用命令
|
||||||
clashctl 命令 [选项]
|
clashon 🚀 开启代理
|
||||||
|
clashoff ⛔ 关闭代理
|
||||||
|
clashctl select 💫 选择节点
|
||||||
|
🕹️ 控制台
|
||||||
|
clashui 🕹️ 查看 Web 控制台
|
||||||
|
clashsecret 🔑 查看或设置 Web 密钥
|
||||||
|
📦 订阅
|
||||||
|
clashctl add ➕ 添加订阅
|
||||||
|
clashctl use 💱 切换订阅
|
||||||
|
clashctl ls 📡 查看订阅列表
|
||||||
|
📌 高级
|
||||||
|
clashctl tun 🧪 Tun 模式管理
|
||||||
|
clashctl mixin 🧩 Mixin 配置管理
|
||||||
|
clashctl sub 🧩 订阅高级管理(启用 / 禁用 / 重命名 / 删除)
|
||||||
|
clashctl upgrade 🚀 升级当前或指定内核
|
||||||
|
clashctl update 🔄 更新项目代码
|
||||||
|
📜 日志
|
||||||
|
clashctl doctor 🩺 诊断面板
|
||||||
|
clashctl log/logs 📜 查看日志
|
||||||
|
|
||||||
指令:
|
💡 显示更多帮助命令:clashctl -h
|
||||||
on 开启代理
|
💡 更多高级能力:clashctl help advanced
|
||||||
off 关闭代理
|
|
||||||
start 启动 Clash
|
|
||||||
stop 停止 Clash
|
|
||||||
restart 重启并自动应用当前配置
|
|
||||||
status 查看当前状态
|
|
||||||
update 更新到最新版本并自动应用配置
|
|
||||||
mode 查看当前运行模式(systemd/script/none)
|
|
||||||
ui 输出 Dashboard 地址
|
|
||||||
secret 输出当前 secret
|
|
||||||
doctor 健康检查
|
|
||||||
logs [-f] [-n 100] 查看日志
|
|
||||||
sub show|update 查看订阅地址 / 输入或更新订阅并立即生效
|
|
||||||
tun status|on|off 查看/启用/关闭 Tun
|
|
||||||
mixin status|on|off 查看/启用/关闭 Mixin
|
|
||||||
|
|
||||||
选项:
|
|
||||||
-h, --help 显示帮助信息
|
|
||||||
```
|
```
|
||||||
|
|
||||||
------
|
------
|
||||||
@@ -77,24 +81,27 @@ bash install.sh
|
|||||||
```bash
|
```bash
|
||||||
$ clashui
|
$ clashui
|
||||||
╔═══════════════════════════════════════════════╗
|
╔═══════════════════════════════════════════════╗
|
||||||
║ 🐱 Web 控制台 ║
|
║ 🐱 Web 控制台 ║
|
||||||
║═══════════════════════════════════════════════║
|
║═══════════════════════════════════════════════║
|
||||||
║ ║
|
║ ║
|
||||||
║ 🔓 注意放行端口:9090 ║
|
║ 🔓 注意放行端口:9090 ║
|
||||||
║ 🏠 内网:http://192.168.0.1:9090/ui ║
|
║ 📶 状态:可访问 ║
|
||||||
║ 🌏 公网:http://8.8.8.8:9090/ui ║
|
║ 🏠 内网:http://192.168.0.1:9090/ui ║
|
||||||
║ ☁️ 公共:http://board.zash.run.place ║
|
║ ☁️ 公共:http://board.zash.run.place ║
|
||||||
|
║ 🌏 公网:http://8.8.8.8:9090/ui ║
|
||||||
|
║ 🔑 密钥:dada289edb457b59 ║
|
||||||
║ ║
|
║ ║
|
||||||
╚═══════════════════════════════════════════════╝
|
╚═══════════════════════════════════════════════╝
|
||||||
|
|
||||||
$ clashctl secret mysecret
|
$ clashsecret mysecret
|
||||||
🐱 密钥更新成功,已重启生效
|
🐱 密钥更新成功,已重启生效
|
||||||
|
|
||||||
$ clashctl secret
|
$ clashsecret
|
||||||
🐱 当前密钥:mysecret
|
🐱 当前密钥:mysecret
|
||||||
```
|
```
|
||||||
|
|
||||||
- 可通过浏览器打开 `Web` 控制台进行可视化操作,例如切换节点、查看日志等。
|
- 可通过浏览器打开 `Web` 控制台进行可视化操作,例如切换节点、查看日志等。
|
||||||
|
- `clashctl secret` 作为兼容入口继续保留,日常优先使用 `clashsecret`。
|
||||||
- 默认使用 [zashboard](https://github.com/Zephyruso/zashboard) 作为控制台前端,如需更换可自行配置。
|
- 默认使用 [zashboard](https://github.com/Zephyruso/zashboard) 作为控制台前端,如需更换可自行配置。
|
||||||
- 若需将控制台暴露到公网,建议定期更换访问密钥,或通过 `SSH` 端口转发方式进行安全访问。
|
- 若需将控制台暴露到公网,建议定期更换访问密钥,或通过 `SSH` 端口转发方式进行安全访问。
|
||||||
|
|
||||||
@@ -103,111 +110,188 @@ $ clashctl secret
|
|||||||
|
|
||||||
## 🧰 常用管理命令
|
## 🧰 常用管理命令
|
||||||
|
|
||||||
统一管理入口(推荐使用):
|
|
||||||
|
|
||||||
```
|
|
||||||
clashctl status
|
|
||||||
clashctl start
|
|
||||||
clashctl restart
|
|
||||||
clashctl update
|
|
||||||
clashctl set-url "https://example.com/your-subscribe"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 多订阅管理
|
### 多订阅管理
|
||||||
|
|
||||||
```
|
```
|
||||||
clashctl sub add office "https://example.com/office"
|
clashctl add <订阅链接> <名称>
|
||||||
clashctl sub add personal "https://example.com/personal"
|
clashctl use
|
||||||
|
clashctl ls
|
||||||
|
clashctl sub
|
||||||
clashctl sub list
|
clashctl sub list
|
||||||
clashctl sub use personal
|
clashctl sub enable <名称>
|
||||||
clashctl sub update
|
clashctl sub disable <名称>
|
||||||
clashctl sub log
|
clashctl sub rename <旧名称> <新名称>
|
||||||
|
clashctl sub remove <名称>
|
||||||
```
|
```
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
## 🏗️ 架构设计
|
## 🏗️ 架构设计架构简述
|
||||||
|
|
||||||
```text
|
项目当前可以按三层理解:
|
||||||
.env / 订阅
|
|
||||||
↓
|
### Control
|
||||||
generate(配置生成)
|
|
||||||
↓
|
用户入口层。
|
||||||
runtime/config.yaml(运行态)
|
|
||||||
↓
|
- `clashctl`
|
||||||
Clash 内核运行(systemd / script)
|
- `clashon`
|
||||||
↓
|
- `clashoff`
|
||||||
status / doctor(状态观测)
|
- `status`
|
||||||
|
- `doctor`
|
||||||
|
- `ui`
|
||||||
|
- `select`
|
||||||
|
|
||||||
|
Control 层负责把常用动作收口成可理解的命令和反馈。
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
配置生成层。
|
||||||
|
|
||||||
|
- 多订阅保存
|
||||||
|
- 单 active 主订阅
|
||||||
|
- active-only 编译链
|
||||||
|
- 订阅下载 / 转换 / 校验
|
||||||
|
- `config/mixin.yaml` 运行补丁
|
||||||
|
- 输出 `runtime/config.yaml`
|
||||||
|
|
||||||
|
当前规则很明确:`generate_config` 只处理当前 active 主订阅。
|
||||||
|
|
||||||
|
### Runtime
|
||||||
|
|
||||||
|
实际运行层。
|
||||||
|
|
||||||
|
- `runtime/` 是唯一运行时容器
|
||||||
|
- 后端可以是 `systemd`、`systemd-user` 或 `script`
|
||||||
|
- 运行配置是 `runtime/config.yaml`
|
||||||
|
- 日志、状态、缓存和运行时产物都收敛到 runtime 体系
|
||||||
|
|
||||||
|
## 配置说明
|
||||||
|
|
||||||
|
### `.env`
|
||||||
|
|
||||||
|
`.env` 用于覆盖安装和运行参数。常用项包括:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
KERNEL_TYPE=mihomo
|
||||||
|
MIXED_PORT=7890
|
||||||
|
EXTERNAL_CONTROLLER=0.0.0.0:9090
|
||||||
|
CLASH_CONTROLLER_SECRET=your-secret
|
||||||
|
CLASH_SUBSCRIPTION_URL=https://example.com/sub
|
||||||
|
MIHOMO_VERSION=latest
|
||||||
|
CLASH_VERSION=latest
|
||||||
|
YQ_VERSION=v4.44.3
|
||||||
|
SUBCONVERTER_VERSION=v0.9.0
|
||||||
|
MIHOMO_DOWNLOAD_BASE=https://github.com/MetaCubeX/mihomo/releases/download
|
||||||
|
CLASH_DOWNLOAD_BASE=https://github.com/WindSpiritSR/clash/releases/download
|
||||||
```
|
```
|
||||||
|
|
||||||
核心原则:
|
按需设置即可,不需要每项都写。
|
||||||
|
|
||||||
- 配置生成 ≠ 运行
|
### `config/mixin.yaml`
|
||||||
- 运行环境隔离
|
|
||||||
- 状态必须可观测
|
用于对最终运行配置做补丁:
|
||||||
|
|
||||||
|
- `override` 覆盖字段
|
||||||
|
- `prepend` 把数组项放到原始配置前面
|
||||||
|
- `append` 把数组项放到原始配置后面
|
||||||
|
|
||||||
|
查看当前模板:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clashctl mixin
|
||||||
|
```
|
||||||
|
|
||||||
|
编辑:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clashctl mixin edit
|
||||||
|
```
|
||||||
|
|
||||||
|
查看最终运行配置:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clashctl mixin runtime
|
||||||
|
```
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
## 🔄 配置修改与更新
|
## 🔄 更新
|
||||||
|
|
||||||
### 修改 Clash 配置并重启
|
```bash
|
||||||
|
|
||||||
```
|
|
||||||
vim runtime/config.yaml
|
|
||||||
clashctl restart
|
|
||||||
```
|
|
||||||
|
|
||||||
> `restart` 不会更新订阅
|
|
||||||
|
|
||||||
### 更新订阅
|
|
||||||
|
|
||||||
```
|
|
||||||
clashctl update
|
clashctl update
|
||||||
|
clashctl upgrade
|
||||||
|
clashctl upgrade mihomo
|
||||||
|
clashctl upgrade clash
|
||||||
```
|
```
|
||||||
|
|
||||||
或指定订阅:
|
`update` 用于更新项目代码与运行依赖。`upgrade` 用于升级当前或指定代理内核。
|
||||||
|
|
||||||
```
|
|
||||||
clashctl sub update personal
|
|
||||||
```
|
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
## 🧩 Mixin 配置(可选)
|
## 🧩 Mixin 配置
|
||||||
|
|
||||||
用于追加或覆盖 Clash 配置。
|
|
||||||
|
|
||||||
- 默认读取:`config/mixin.d/*.yaml`(按文件名排序)
|
|
||||||
- 也可在 `.env` 中指定:
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clashctl mixin
|
||||||
|
clashctl mixin edit
|
||||||
|
clashctl mixin raw
|
||||||
|
clashctl mixin runtime
|
||||||
```
|
```
|
||||||
export CLASH_MIXIN_DIR='config/mixin.d'
|
|
||||||
export CLASH_MIXIN_PATHS='config/mixin.d/base.yaml,config/mixin.d/rules.yaml'
|
Mixin 是运行配置补丁,不是订阅管理。它通过 `config/mixin.yaml` 对当前 active 订阅生成的运行配置执行:
|
||||||
|
|
||||||
|
- `override`
|
||||||
|
- `prepend`
|
||||||
|
- `append`
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
override:
|
||||||
|
dns:
|
||||||
|
enable: true
|
||||||
|
|
||||||
|
prepend:
|
||||||
|
proxies: []
|
||||||
|
proxy-groups: []
|
||||||
|
rules:
|
||||||
|
- DOMAIN-SUFFIX,example.com,DIRECT
|
||||||
|
|
||||||
|
append:
|
||||||
|
proxies: []
|
||||||
|
proxy-groups: []
|
||||||
|
rules:
|
||||||
|
- MATCH,节点选择
|
||||||
```
|
```
|
||||||
|
|
||||||
|
编辑后执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clashctl mixin edit
|
||||||
|
```
|
||||||
|
|
||||||
|
它会重新生成配置;如果代理正在运行,会自动重启应用。
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
## 🌐 Tun 模式(可选)
|
## 🌐 Tun 模式
|
||||||
|
|
||||||
需 Clash Meta / Premium 支持,在 `.env` 中配置:
|
```bash
|
||||||
|
clashctl tun on
|
||||||
```
|
clashctl tun off
|
||||||
export CLASH_TUN_ENABLE=true
|
clashctl tun doctor
|
||||||
export CLASH_TUN_STACK=system
|
clashctl tun logs
|
||||||
export CLASH_TUN_AUTO_ROUTE=true
|
|
||||||
export CLASH_TUN_AUTO_REDIRECT=false
|
|
||||||
export CLASH_TUN_STRICT_ROUTE=false
|
|
||||||
export CLASH_TUN_DNS_HIJACK='any:53'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
------
|
Tun 用于透明接管链路。`tun on` 是动作反馈,展示当前关键配置和简短状态;完整证据请看:
|
||||||
|
|
||||||
## ⛔ 停止服务
|
```bash
|
||||||
|
clashctl tun doctor
|
||||||
|
```
|
||||||
|
|
||||||
```
|
Tun 判断不会简单把 `root` 等同于拥有 `CAP_NET_ADMIN`,也不会把 main table 默认路由未切换直接等同于 Tun 未生效。诊断会结合运行后端、容器环境、进程能力、Tun adapter、policy routing、路由表和日志证据。
|
||||||
clashctl stop
|
|
||||||
proxy_off
|
|
||||||
```
|
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
@@ -217,38 +301,6 @@ proxy_off
|
|||||||
bash uninstall.sh
|
bash uninstall.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## subconverter 多架构支持
|
|
||||||
|
|
||||||
`subconverter` 用于将订阅内容转换为标准 clash 配置。默认会尝试以下位置:
|
|
||||||
|
|
||||||
- `tools/subconverter/subconverter`
|
|
||||||
- `tools/subconverter/subconverter-<arch>`
|
|
||||||
- `tools/subconverter/bin/subconverter-<arch>`
|
|
||||||
|
|
||||||
其中 `<arch>` 取值为:
|
|
||||||
|
|
||||||
- `linux-amd64`
|
|
||||||
- `linux-arm64`
|
|
||||||
- `linux-armv7`
|
|
||||||
|
|
||||||
自动下载默认使用 `https://github.com/tindy2013/subconverter/releases/latest/download/subconverter_{arch}.tar.gz`,
|
|
||||||
如果需要自定义来源或关闭下载,可以设置:
|
|
||||||
|
|
||||||
- `SUBCONVERTER_PATH`:指定自定义 `subconverter` 可执行文件路径。
|
|
||||||
- `SUBCONVERTER_AUTO_DOWNLOAD=false`:关闭自动下载(默认会尝试自动下载,需 `curl`/`wget`)。
|
|
||||||
- `SUBCONVERTER_DOWNLOAD_URL_TEMPLATE`:下载模板,使用 `{arch}` 占位符,如:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export SUBCONVERTER_AUTO_DOWNLOAD=true
|
|
||||||
export SUBCONVERTER_DOWNLOAD_URL_TEMPLATE='https://example.com/subconverter_{arch}.tar.gz'
|
|
||||||
```
|
|
||||||
|
|
||||||
当 `subconverter` 不可用时会自动跳过转换,并提示警告。
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## 设置代理
|
## 设置代理
|
||||||
1. 开启 IP 转发
|
1. 开启 IP 转发
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@ if [ -n "$(subscription_url 2>/dev/null || true)" ]; then
|
|||||||
write_runtime_value "INSTALL_VERIFY_CONTROLLER_READY" "false"
|
write_runtime_value "INSTALL_VERIFY_CONTROLLER_READY" "false"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "🔴 安装未完成:订阅编译失败"
|
echo "❗ 安装未完成:订阅编译失败"
|
||||||
if [ -n "$(read_build_value "BUILD_LAST_ERROR_SUMMARY" 2>/dev/null || true)" ]; then
|
if [ -n "$(read_build_value "BUILD_LAST_ERROR_SUMMARY" 2>/dev/null || true)" ]; then
|
||||||
echo "❌ 原因:$(read_build_value "BUILD_LAST_ERROR_SUMMARY" 2>/dev/null || true)"
|
echo "❌ 原因:$(read_build_value "BUILD_LAST_ERROR_SUMMARY" 2>/dev/null || true)"
|
||||||
fi
|
fi
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 199 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 364 KiB |
@@ -154,10 +154,10 @@ _clash_alias_run_on() {
|
|||||||
|
|
||||||
_clash_alias_prepare_on || return $?
|
_clash_alias_prepare_on || return $?
|
||||||
|
|
||||||
echo "🟢 正在开启代理..."
|
echo "🐱 正在开启代理..."
|
||||||
|
|
||||||
on_output="$(mktemp "${TMPDIR:-/tmp}/clashon.XXXXXX")" || {
|
on_output="$(mktemp "${TMPDIR:-/tmp}/clashon.XXXXXX")" || {
|
||||||
echo "🔴 开启代理失败:无法创建临时输出文件" >&2
|
echo "❗ 开启代理失败:无法创建临时输出文件" >&2
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ _clash_alias_run_on() {
|
|||||||
sed 's/^/ /' "$on_output" >&2
|
sed 's/^/ /' "$on_output" >&2
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "🔴 开启代理失败(底层返回码:$on_rc)" >&2
|
echo "❗ 开启代理失败(底层返回码:$on_rc)" >&2
|
||||||
if [ -s "$on_output" ]; then
|
if [ -s "$on_output" ]; then
|
||||||
sed 's/^/ /' "$on_output" >&2
|
sed 's/^/ /' "$on_output" >&2
|
||||||
else
|
else
|
||||||
@@ -205,7 +205,7 @@ _clash_alias_run_on() {
|
|||||||
|
|
||||||
_clash_alias_after_on || {
|
_clash_alias_after_on || {
|
||||||
on_rc=$?
|
on_rc=$?
|
||||||
echo "🔴 开启代理失败:当前 Shell 代理环境同步失败(返回码:$on_rc)" >&2
|
echo "❗ 开启代理失败:当前 Shell 代理环境同步失败(返回码:$on_rc)" >&2
|
||||||
return "$on_rc"
|
return "$on_rc"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+102
-100
@@ -32,8 +32,8 @@ Usage:
|
|||||||
ls 📡 查看订阅列表
|
ls 📡 查看订阅列表
|
||||||
|
|
||||||
🕹️ Control:
|
🕹️ Control:
|
||||||
ui 🕹️ 查看 Web 控制台
|
clashui 🕹️ 查看 Web 控制台
|
||||||
secret 🔑 查看或设置 Web 密钥
|
clashsecret 🔑 查看或设置 Web 密钥
|
||||||
|
|
||||||
🩺 Diagnose:
|
🩺 Diagnose:
|
||||||
doctor 🩺 诊断环境与运行状态
|
doctor 🩺 诊断环境与运行状态
|
||||||
@@ -215,7 +215,7 @@ print_on_feedback() {
|
|||||||
next_action="$(system_state_default_action 2>/dev/null || echo 'clashctl status')"
|
next_action="$(system_state_default_action 2>/dev/null || echo 'clashctl status')"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "🟢 已开启代理环境"
|
echo "🐱 已开启代理环境"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
if [ -n "${mixed_port:-}" ] && [ "$mixed_port" != "null" ]; then
|
if [ -n "${mixed_port:-}" ] && [ "$mixed_port" != "null" ]; then
|
||||||
@@ -597,8 +597,8 @@ status_tun_effective_text() {
|
|||||||
s="$(status_tun_effective_status)"
|
s="$(status_tun_effective_status)"
|
||||||
|
|
||||||
case "$s" in
|
case "$s" in
|
||||||
effective) echo "🟢 已生效" ;;
|
effective) echo "🐱 已生效" ;;
|
||||||
*) echo "🔴 未生效" ;;
|
*) echo "❗ 未生效" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -769,10 +769,10 @@ system_state_risk_text() {
|
|||||||
load_system_state
|
load_system_state
|
||||||
|
|
||||||
case "$RISK_LEVEL" in
|
case "$RISK_LEVEL" in
|
||||||
low) echo "🟢 低" ;;
|
low) echo "🐱 低" ;;
|
||||||
medium) echo "🟡 中" ;;
|
medium) echo "🟡 中" ;;
|
||||||
high) echo "🟠 高" ;;
|
high) echo "🟠 高" ;;
|
||||||
critical) echo "🔴 严重" ;;
|
critical) echo "❗ 严重" ;;
|
||||||
*) echo "⚪ 未知" ;;
|
*) echo "⚪ 未知" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -950,7 +950,7 @@ compute_box_width() {
|
|||||||
[ "$line_width" -gt "$max_len" ] && max_len="$line_width"
|
[ "$line_width" -gt "$max_len" ] && max_len="$line_width"
|
||||||
done
|
done
|
||||||
|
|
||||||
ui_box_width=$((max_len + 8))
|
ui_box_width=$((max_len + 14))
|
||||||
}
|
}
|
||||||
|
|
||||||
box_border_top() {
|
box_border_top() {
|
||||||
@@ -998,7 +998,7 @@ box_empty() {
|
|||||||
box_section_line() {
|
box_section_line() {
|
||||||
local text="$1"
|
local text="$1"
|
||||||
local inner_width=$((ui_box_width - 2))
|
local inner_width=$((ui_box_width - 2))
|
||||||
local content=" $text"
|
local content=" $text"
|
||||||
local content_len
|
local content_len
|
||||||
content_len="$(box_text_width "$content")"
|
content_len="$(box_text_width "$content")"
|
||||||
local right_pad=$((inner_width - content_len))
|
local right_pad=$((inner_width - content_len))
|
||||||
@@ -1066,10 +1066,10 @@ print_config_apply_feedback() {
|
|||||||
|
|
||||||
case "${build_status:-unknown}" in
|
case "${build_status:-unknown}" in
|
||||||
success)
|
success)
|
||||||
echo "🟢 构建结果:success"
|
echo "🐱 构建结果:success"
|
||||||
;;
|
;;
|
||||||
failed)
|
failed)
|
||||||
echo "🔴 构建结果:failed"
|
echo "❗ 构建结果:failed"
|
||||||
;;
|
;;
|
||||||
blocked)
|
blocked)
|
||||||
echo "🚨 构建结果:blocked"
|
echo "🚨 构建结果:blocked"
|
||||||
@@ -1081,7 +1081,7 @@ print_config_apply_feedback() {
|
|||||||
|
|
||||||
case "${build_applied:-unknown}" in
|
case "${build_applied:-unknown}" in
|
||||||
true)
|
true)
|
||||||
echo "🟢 是否应用:true"
|
echo "🐱 是否应用:true"
|
||||||
;;
|
;;
|
||||||
false)
|
false)
|
||||||
echo "🚨 是否应用:false"
|
echo "🚨 是否应用:false"
|
||||||
@@ -1098,9 +1098,9 @@ print_config_apply_feedback() {
|
|||||||
|
|
||||||
main_feedback_runtime_state() {
|
main_feedback_runtime_state() {
|
||||||
if status_is_running; then
|
if status_is_running; then
|
||||||
ui_kv "🟢" "运行状态" "已运行"
|
ui_kv "🐱" "运行状态" "已运行"
|
||||||
else
|
else
|
||||||
ui_kv "🔴" "运行状态" "未运行"
|
ui_kv "❗" "运行状态" "未运行"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1192,21 +1192,21 @@ print_select_context() {
|
|||||||
local current_proxy
|
local current_proxy
|
||||||
|
|
||||||
if ! status_is_running; then
|
if ! status_is_running; then
|
||||||
ui_kv "🔴" "代理状态" "未运行"
|
ui_kv "❗" "代理状态" "未运行"
|
||||||
ui_next "clashon"
|
ui_next "clashon"
|
||||||
ui_blank
|
ui_blank
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! proxy_controller_reachable 2>/dev/null; then
|
if ! proxy_controller_reachable 2>/dev/null; then
|
||||||
ui_kv "🔴" "当前节点" "控制器不可访问"
|
ui_kv "❗" "当前节点" "控制器不可访问"
|
||||||
ui_next "clashctl doctor"
|
ui_next "clashctl doctor"
|
||||||
ui_blank
|
ui_blank
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$(proxy_group_count 2>/dev/null || echo 0)" -le 0 ]; then
|
if [ "$(proxy_group_count 2>/dev/null || echo 0)" -le 0 ]; then
|
||||||
ui_kv "🔴" "当前节点" "暂无可切换策略组"
|
ui_kv "❗" "当前节点" "暂无可切换策略组"
|
||||||
ui_next "clashctl status --verbose"
|
ui_next "clashctl status --verbose"
|
||||||
ui_blank
|
ui_blank
|
||||||
return 1
|
return 1
|
||||||
@@ -1334,7 +1334,7 @@ print_tun_container_gate_feedback() {
|
|||||||
case "$mode" in
|
case "$mode" in
|
||||||
host)
|
host)
|
||||||
ui_kv "💻" "环境模式" "主机环境"
|
ui_kv "💻" "环境模式" "主机环境"
|
||||||
ui_kv "🟢" "容器裁决" "允许正常开启"
|
ui_kv "🐱" "容器裁决" "允许正常开启"
|
||||||
;;
|
;;
|
||||||
container-safe)
|
container-safe)
|
||||||
ui_kv "💻" "环境模式" "容器环境"
|
ui_kv "💻" "环境模式" "容器环境"
|
||||||
@@ -1343,8 +1343,8 @@ print_tun_container_gate_feedback() {
|
|||||||
;;
|
;;
|
||||||
container-risky)
|
container-risky)
|
||||||
ui_kv "💻" "环境模式" "容器环境"
|
ui_kv "💻" "环境模式" "容器环境"
|
||||||
ui_kv "🔴" "容器裁决" "高风险,已阻断开启"
|
ui_kv "❗" "容器裁决" "高风险,已阻断开启"
|
||||||
[ -n "${reason:-}" ] && ui_kv "🔴" "阻断原因" "$reason"
|
[ -n "${reason:-}" ] && ui_kv "❗" "阻断原因" "$reason"
|
||||||
ui_next "clashctl tun doctor"
|
ui_next "clashctl tun doctor"
|
||||||
ui_blank
|
ui_blank
|
||||||
;;
|
;;
|
||||||
@@ -1377,12 +1377,12 @@ print_tun_on_feedback() {
|
|||||||
|
|
||||||
case "$verify_result" in
|
case "$verify_result" in
|
||||||
ok)
|
ok)
|
||||||
status_icon="🟢"
|
status_icon="🐱"
|
||||||
status_text="已生效"
|
status_text="已生效"
|
||||||
detail="已通过 Tun 即时验证"
|
detail="已通过 Tun 即时验证"
|
||||||
;;
|
;;
|
||||||
policy-routing-likely-effective)
|
policy-routing-likely-effective)
|
||||||
status_icon="🟢"
|
status_icon="🐱"
|
||||||
status_text="已生效"
|
status_text="已生效"
|
||||||
if tun_log_tun_source_line >/dev/null 2>&1; then
|
if tun_log_tun_source_line >/dev/null 2>&1; then
|
||||||
detail="已检测到 Tun 适配器、policy routing 与 Tun 源地址流量"
|
detail="已检测到 Tun 适配器、policy routing 与 Tun 源地址流量"
|
||||||
@@ -1391,7 +1391,7 @@ print_tun_on_feedback() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
disabled-in-state|disabled-in-runtime-config|tun-disabled|runtime-not-running|controller-unreachable)
|
disabled-in-state|disabled-in-runtime-config|tun-disabled|runtime-not-running|controller-unreachable)
|
||||||
status_icon="🔴"
|
status_icon="❗"
|
||||||
status_text="未生效"
|
status_text="未生效"
|
||||||
detail="即时验证未通过:$verify_result"
|
detail="即时验证未通过:$verify_result"
|
||||||
;;
|
;;
|
||||||
@@ -1425,7 +1425,7 @@ print_tun_off_feedback() {
|
|||||||
|
|
||||||
case "$verify_result" in
|
case "$verify_result" in
|
||||||
ok)
|
ok)
|
||||||
ui_kv "🟢" "验证结果" "Tun 已关闭并完成回滚检查"
|
ui_kv "🐱" "验证结果" "Tun 已关闭并完成回滚检查"
|
||||||
[ -n "${route_dev:-}" ] && ui_kv "🌐" "当前默认路由设备" "$route_dev"
|
[ -n "${route_dev:-}" ] && ui_kv "🌐" "当前默认路由设备" "$route_dev"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@@ -1912,9 +1912,9 @@ print_status_summary_compact() {
|
|||||||
tun_text="$(status_tun_effective_text)"
|
tun_text="$(status_tun_effective_text)"
|
||||||
|
|
||||||
if status_is_running; then
|
if status_is_running; then
|
||||||
running_text="🟢 已开启"
|
running_text="🐱 已开启"
|
||||||
else
|
else
|
||||||
running_text="🔴 未开启"
|
running_text="❗ 未开启"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
user_connectivity="$(connectivity_issue_text)"
|
user_connectivity="$(connectivity_issue_text)"
|
||||||
@@ -1951,7 +1951,7 @@ print_status_summary_compact() {
|
|||||||
echo
|
echo
|
||||||
|
|
||||||
echo "【当前结果】"
|
echo "【当前结果】"
|
||||||
echo "🟢 代理状态:$running_text"
|
echo "🐱 代理状态:$running_text"
|
||||||
echo "🌐 当前可用性:$user_connectivity"
|
echo "🌐 当前可用性:$user_connectivity"
|
||||||
echo "📡 当前订阅:${current_active:-未设置}"
|
echo "📡 当前订阅:${current_active:-未设置}"
|
||||||
echo "🚀 当前节点:$current_proxy_brief"
|
echo "🚀 当前节点:$current_proxy_brief"
|
||||||
@@ -2037,9 +2037,9 @@ print_status_summary_verbose() {
|
|||||||
build_applied_reason="$(status_runtime_build_applied_reason 2>/dev/null || true)"
|
build_applied_reason="$(status_runtime_build_applied_reason 2>/dev/null || true)"
|
||||||
|
|
||||||
if status_is_running; then
|
if status_is_running; then
|
||||||
running_text="🟢 已开启"
|
running_text="🐱 已开启"
|
||||||
else
|
else
|
||||||
running_text="🔴 未开启"
|
running_text="❗ 未开启"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
controller_ok="false"
|
controller_ok="false"
|
||||||
@@ -2096,7 +2096,7 @@ print_status_summary_verbose() {
|
|||||||
echo
|
echo
|
||||||
|
|
||||||
echo "【当前结果】"
|
echo "【当前结果】"
|
||||||
echo "🟢 代理状态:$running_text"
|
echo "🐱 代理状态:$running_text"
|
||||||
echo "🌐 当前可用性:$user_connectivity"
|
echo "🌐 当前可用性:$user_connectivity"
|
||||||
echo "📡 当前订阅:${current_active:-未设置}"
|
echo "📡 当前订阅:${current_active:-未设置}"
|
||||||
echo "🚀 当前节点:$current_proxy_brief"
|
echo "🚀 当前节点:$current_proxy_brief"
|
||||||
@@ -2149,9 +2149,9 @@ print_status_summary_verbose() {
|
|||||||
|
|
||||||
echo "【Tun 状态】"
|
echo "【Tun 状态】"
|
||||||
if [ "$tun_enabled" = "true" ]; then
|
if [ "$tun_enabled" = "true" ]; then
|
||||||
echo "🟢 Tun 开关:已开启"
|
echo "🐱 Tun 开关:已开启"
|
||||||
else
|
else
|
||||||
echo "🔴 Tun 开关:未开启"
|
echo "❗ Tun 开关:未开启"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "🧪 Tun 生效:${tun_effective:-未知}"
|
echo "🧪 Tun 生效:${tun_effective:-未知}"
|
||||||
@@ -2170,7 +2170,7 @@ print_status_summary_verbose() {
|
|||||||
echo "🧩 最近编译:未知"
|
echo "🧩 最近编译:未知"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[ -n "${build_active_sources:-}" ] && echo "🟢 实际参与编译:$build_active_sources"
|
[ -n "${build_active_sources:-}" ] && echo "🐱 实际参与编译:$build_active_sources"
|
||||||
[ -n "${build_failed_active_sources:-}" ] && echo "❌ 编译失败源:$build_failed_active_sources"
|
[ -n "${build_failed_active_sources:-}" ] && echo "❌ 编译失败源:$build_failed_active_sources"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
@@ -2187,7 +2187,7 @@ print_status_summary_verbose() {
|
|||||||
|
|
||||||
case "${build_applied:-}" in
|
case "${build_applied:-}" in
|
||||||
true)
|
true)
|
||||||
echo "🟢 最近构建应用:true @ ${build_applied_time:-unknown}"
|
echo "🐱 最近构建应用:true @ ${build_applied_time:-unknown}"
|
||||||
;;
|
;;
|
||||||
false)
|
false)
|
||||||
echo "🚨 最近构建应用:false @ ${build_applied_time:-unknown}"
|
echo "🚨 最近构建应用:false @ ${build_applied_time:-unknown}"
|
||||||
@@ -2357,8 +2357,8 @@ cmd_ui_box() {
|
|||||||
|
|
||||||
line0="🔓 注意放行端口:${6:-unknown}"
|
line0="🔓 注意放行端口:${6:-unknown}"
|
||||||
[ -n "${1:-}" ] && line1="📶 状态:$1"
|
[ -n "${1:-}" ] && line1="📶 状态:$1"
|
||||||
[ -n "${2:-}" ] && line2="💻 本机:$2"
|
[ -n "${3:-}" ] && line2="🏠 内网:$3"
|
||||||
[ -n "${3:-}" ] && line3="🏠 局域网:$3"
|
line3="📡 公共:http://board.zash.run.place"
|
||||||
[ -n "${4:-}" ] && line4="🌏 公网:$4"
|
[ -n "${4:-}" ] && line4="🌏 公网:$4"
|
||||||
[ -n "${secret:-}" ] && line5="🔑 密钥:$secret"
|
[ -n "${secret:-}" ] && line5="🔑 密钥:$secret"
|
||||||
|
|
||||||
@@ -2390,8 +2390,8 @@ cmd_ui_help_summary() {
|
|||||||
printf ' %-18s %s\n' "clashoff" "⛔ 关闭代理"
|
printf ' %-18s %s\n' "clashoff" "⛔ 关闭代理"
|
||||||
printf ' %-18s %s\n' "clashctl select" "💫 选择节点"
|
printf ' %-18s %s\n' "clashctl select" "💫 选择节点"
|
||||||
echo "🕹️ 控制台"
|
echo "🕹️ 控制台"
|
||||||
printf ' %-18s %s\n' "clashctl ui" "🕹️ 查看 Web 控制台"
|
printf ' %-18s %s\n' "clashui" "🕹️ 查看 Web 控制台"
|
||||||
printf ' %-18s %s\n' "clashctl secret" "🔑 查看或设置 Web 密钥"
|
printf ' %-18s %s\n' "clashsecret" "🔑 查看或设置 Web 密钥"
|
||||||
echo "📦 订阅"
|
echo "📦 订阅"
|
||||||
printf ' %-18s %s\n' "clashctl add" "➕ 添加订阅"
|
printf ' %-18s %s\n' "clashctl add" "➕ 添加订阅"
|
||||||
printf ' %-18s %s\n' "clashctl use" "💱 切换订阅"
|
printf ' %-18s %s\n' "clashctl use" "💱 切换订阅"
|
||||||
@@ -3175,7 +3175,7 @@ cmd_doctor() {
|
|||||||
if doctor_problem_lines | grep -q .; then
|
if doctor_problem_lines | grep -q .; then
|
||||||
doctor_problem_lines | sed 's/^/ /'
|
doctor_problem_lines | sed 's/^/ /'
|
||||||
else
|
else
|
||||||
echo " 🟢 未发现明显问题"
|
echo " 🐱 未发现明显问题"
|
||||||
fi
|
fi
|
||||||
ui_blank
|
ui_blank
|
||||||
|
|
||||||
@@ -3216,7 +3216,7 @@ cmd_dev() {
|
|||||||
bash "$PROJECT_DIR/uninstall.sh" --dev-reset
|
bash "$PROJECT_DIR/uninstall.sh" --dev-reset
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "🟢 开发重置完成"
|
echo "🐱 开发重置完成"
|
||||||
echo "🧩 保留内容:项目目录、已下载依赖、调试环境"
|
echo "🧩 保留内容:项目目录、已下载依赖、调试环境"
|
||||||
echo "👉 下一步:重新执行 install.sh 或 clashctl status"
|
echo "👉 下一步:重新执行 install.sh 或 clashctl status"
|
||||||
echo
|
echo
|
||||||
@@ -3245,7 +3245,7 @@ cmd_config_show() {
|
|||||||
ui_kv "🚩" "当前主订阅" "${active:-未设置}"
|
ui_kv "🚩" "当前主订阅" "${active:-未设置}"
|
||||||
ui_kv "🚀" "当前内核" "${kernel:-mihomo}"
|
ui_kv "🚀" "当前内核" "${kernel:-mihomo}"
|
||||||
ui_kv "🧩" "编译模式" "active-only"
|
ui_kv "🧩" "编译模式" "active-only"
|
||||||
ui_kv "🟢" "最近构建" "${build_status:-unknown}${build_time:+ @ ${build_time}}"
|
ui_kv "🐱" "最近构建" "${build_status:-unknown}${build_time:+ @ ${build_time}}"
|
||||||
ui_kv "🧩" "配置来源" "${config_source:-unknown}"
|
ui_kv "🧩" "配置来源" "${config_source:-unknown}"
|
||||||
ui_blank
|
ui_blank
|
||||||
ui_next "clashctl status"
|
ui_next "clashctl status"
|
||||||
@@ -3463,7 +3463,7 @@ cmd_mixin_edit() {
|
|||||||
|
|
||||||
if status_is_running; then
|
if status_is_running; then
|
||||||
service_restart
|
service_restart
|
||||||
echo "🟢 Mixin 已生效(已自动重启)"
|
echo "🐱 Mixin 已生效(已自动重启)"
|
||||||
else
|
else
|
||||||
echo "🟡 Mixin 已写入(下次启动生效)"
|
echo "🟡 Mixin 已写入(下次启动生效)"
|
||||||
fi
|
fi
|
||||||
@@ -3588,9 +3588,9 @@ doctor_risk_level() {
|
|||||||
|
|
||||||
doctor_risk_text() {
|
doctor_risk_text() {
|
||||||
case "$(doctor_risk_level)" in
|
case "$(doctor_risk_level)" in
|
||||||
low) echo "🟢 低" ;;
|
low) echo "🐱 低" ;;
|
||||||
medium) echo "🟡 中" ;;
|
medium) echo "🟡 中" ;;
|
||||||
high) echo "🔴 高" ;;
|
high) echo "❗ 高" ;;
|
||||||
*) echo "⚪ 未知" ;;
|
*) echo "⚪ 未知" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -3623,7 +3623,7 @@ doctor_problem_lines() {
|
|||||||
|
|
||||||
doctor_primary_conclusion() {
|
doctor_primary_conclusion() {
|
||||||
if ! runtime_config_exists; then
|
if ! runtime_config_exists; then
|
||||||
echo "🔴 当前不可用:缺少运行配置"
|
echo "❗ 当前不可用:缺少运行配置"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -3633,11 +3633,11 @@ doctor_primary_conclusion() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if ! proxy_controller_reachable 2>/dev/null; then
|
if ! proxy_controller_reachable 2>/dev/null; then
|
||||||
echo "🔴 当前异常:内核已启动,但控制器不可访问"
|
echo "❗ 当前异常:内核已启动,但控制器不可访问"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "🟢 当前基本可用:代理内核与控制器均正常"
|
echo "🐱 当前基本可用:代理内核与控制器均正常"
|
||||||
}
|
}
|
||||||
|
|
||||||
doctor_recommendation_lines() {
|
doctor_recommendation_lines() {
|
||||||
@@ -3752,39 +3752,30 @@ cmd_secret() {
|
|||||||
case "${1:-}" in
|
case "${1:-}" in
|
||||||
"")
|
"")
|
||||||
current_secret="$(controller_secret 2>/dev/null || true)"
|
current_secret="$(controller_secret 2>/dev/null || true)"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
ui_title "🔑 Web 密钥"
|
|
||||||
|
|
||||||
if [ -n "${current_secret:-}" ] && [ "$current_secret" != "null" ]; then
|
if [ -n "${current_secret:-}" ] && [ "$current_secret" != "null" ]; then
|
||||||
ui_kv "🔑" "当前密钥" "$current_secret"
|
ui_kv "🔑" "当前密钥" "$current_secret"
|
||||||
else
|
else
|
||||||
ui_kv "🚨" "当前密钥" "未设置"
|
ui_kv "🚨" "当前密钥" "未设置"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ui_kv "🐱" "用途" "用于访问 Clash Web 控制台"
|
|
||||||
ui_next "clashctl ui"
|
|
||||||
ui_blank
|
ui_blank
|
||||||
echo
|
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
new_secret="$1"
|
new_secret="$1"
|
||||||
set_controller_secret "$new_secret"
|
set_controller_secret "$new_secret"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
ui_title "🔑 密钥已更新"
|
|
||||||
ui_kv "🔑" "新密钥" "$new_secret"
|
|
||||||
|
|
||||||
if status_is_running; then
|
if status_is_running; then
|
||||||
service_restart
|
service_restart
|
||||||
ui_kv "🟢" "生效状态" "已重启并生效"
|
ui_kv "🐱" "状态" "密钥更新成功,已重启生效"
|
||||||
else
|
else
|
||||||
ui_kv "🟡" "生效状态" "将在下次启动时生效"
|
ui_kv "🐱" "状态" "将在下次启动时生效"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ui_next "clashctl ui"
|
|
||||||
ui_blank
|
ui_blank
|
||||||
echo
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -3803,24 +3794,24 @@ cmd_tun_status() {
|
|||||||
echo
|
echo
|
||||||
|
|
||||||
if [ "$enabled" = "true" ]; then
|
if [ "$enabled" = "true" ]; then
|
||||||
echo "🟢 当前状态:已开启"
|
echo "🐱 当前状态:已开启"
|
||||||
else
|
else
|
||||||
echo "🔴 当前状态:未开启"
|
echo "❗ 当前状态:未开启"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "🔧 Tun stack:$stack"
|
echo "🔧 Tun stack:$stack"
|
||||||
echo "💻 环境类型:$env_type"
|
echo "💻 环境类型:$env_type"
|
||||||
|
|
||||||
if can_manage_tun_safely; then
|
if can_manage_tun_safely; then
|
||||||
echo "🟢 环境检查:满足基础开启条件"
|
echo "🐱 环境检查:满足基础开启条件"
|
||||||
else
|
else
|
||||||
echo "🚨 环境检查:当前不满足基础开启条件"
|
echo "🚨 环境检查:当前不满足基础开启条件"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$effective_status" = "effective" ]; then
|
if [ "$effective_status" = "effective" ]; then
|
||||||
echo "🟢 已生效"
|
echo "🐱 已生效"
|
||||||
else
|
else
|
||||||
echo "🔴 未生效"
|
echo "❗ 未生效"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$enabled" = "true" ]; then
|
if [ "$enabled" = "true" ]; then
|
||||||
@@ -3864,7 +3855,7 @@ cmd_tun_on() {
|
|||||||
|
|
||||||
if ! can_manage_tun_safely; then
|
if ! can_manage_tun_safely; then
|
||||||
echo
|
echo
|
||||||
echo "🔴 Tun 模式无法开启"
|
echo "❗ Tun 模式无法开启"
|
||||||
echo "🚨 原因:当前环境不满足基础 Tun 条件"
|
echo "🚨 原因:当前环境不满足基础 Tun 条件"
|
||||||
echo "👉 下一步:clashctl tun doctor"
|
echo "👉 下一步:clashctl tun doctor"
|
||||||
echo
|
echo
|
||||||
@@ -3993,13 +3984,13 @@ doctor_tun_checks() {
|
|||||||
|
|
||||||
echo "【总体结论】"
|
echo "【总体结论】"
|
||||||
if [ "$process_cap_rc" -eq 0 ]; then
|
if [ "$process_cap_rc" -eq 0 ]; then
|
||||||
echo "🟢 mihomo 进程已检测到 CAP_NET_ADMIN;当前执行环境 capability 不作为主因"
|
echo "🐱 mihomo 进程已检测到 CAP_NET_ADMIN;当前执行环境 capability 不作为主因"
|
||||||
elif [ "$cap_rc" -eq 1 ]; then
|
elif [ "$cap_rc" -eq 1 ]; then
|
||||||
echo "🔴 当前执行环境未检测到 CAP_NET_ADMIN;root 不等于一定拥有 CAP_NET_ADMIN"
|
echo "❗ 当前执行环境未检测到 CAP_NET_ADMIN;root 不等于一定拥有 CAP_NET_ADMIN"
|
||||||
elif can_manage_tun_safely; then
|
elif can_manage_tun_safely; then
|
||||||
echo "🟢 当前环境满足基础 Tun 开启条件"
|
echo "🐱 当前环境满足基础 Tun 开启条件"
|
||||||
else
|
else
|
||||||
echo "🔴 当前环境不满足基础 Tun 开启条件"
|
echo "❗ 当前环境不满足基础 Tun 开启条件"
|
||||||
fi
|
fi
|
||||||
echo "🧪 Tun 是否生效要看 mihomo 进程实际拿到的网络管理能力,能力边界可能来自 systemd unit 或容器环境"
|
echo "🧪 Tun 是否生效要看 mihomo 进程实际拿到的网络管理能力,能力边界可能来自 systemd unit 或容器环境"
|
||||||
echo "🧪 当前 Tun 状态:$runtime_tun_status"
|
echo "🧪 当前 Tun 状态:$runtime_tun_status"
|
||||||
@@ -4014,7 +4005,7 @@ doctor_tun_checks() {
|
|||||||
if [ "$(tun_container_mode 2>/dev/null || echo unknown)" = "container-risky" ]; then
|
if [ "$(tun_container_mode 2>/dev/null || echo unknown)" = "container-risky" ]; then
|
||||||
local gate_reason
|
local gate_reason
|
||||||
gate_reason="$(tun_container_risk_reason 2>/dev/null || true)"
|
gate_reason="$(tun_container_risk_reason 2>/dev/null || true)"
|
||||||
[ -n "${gate_reason:-}" ] && echo "🔴 阻断原因:$gate_reason"
|
[ -n "${gate_reason:-}" ] && echo "❗ 阻断原因:$gate_reason"
|
||||||
fi
|
fi
|
||||||
echo
|
echo
|
||||||
|
|
||||||
@@ -4028,13 +4019,13 @@ doctor_tun_checks() {
|
|||||||
if [ -n "${problem_lines:-}" ]; then
|
if [ -n "${problem_lines:-}" ]; then
|
||||||
printf '%s\n' "$problem_lines" | sed 's/^/ /'
|
printf '%s\n' "$problem_lines" | sed 's/^/ /'
|
||||||
else
|
else
|
||||||
echo " 🟢 未发现明显问题"
|
echo " 🐱 未发现明显问题"
|
||||||
fi
|
fi
|
||||||
echo
|
echo
|
||||||
|
|
||||||
echo "【关键证据】"
|
echo "【关键证据】"
|
||||||
if is_root_user; then
|
if is_root_user; then
|
||||||
echo " 🟢 当前执行用户:root"
|
echo " 🐱 当前执行用户:root"
|
||||||
else
|
else
|
||||||
echo " 🚨 当前执行用户:非 root"
|
echo " 🚨 当前执行用户:非 root"
|
||||||
fi
|
fi
|
||||||
@@ -4042,14 +4033,14 @@ doctor_tun_checks() {
|
|||||||
echo " 💻 是否容器:$(tun_doctor_container_evidence_text "$env_type")"
|
echo " 💻 是否容器:$(tun_doctor_container_evidence_text "$env_type")"
|
||||||
|
|
||||||
if tun_device_exists; then
|
if tun_device_exists; then
|
||||||
echo " 🟢 /dev/net/tun:存在"
|
echo " 🐱 /dev/net/tun:存在"
|
||||||
else
|
else
|
||||||
echo " 🔴 /dev/net/tun:不存在"
|
echo " ❗ /dev/net/tun:不存在"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if tun_device_exists; then
|
if tun_device_exists; then
|
||||||
if tun_device_readable; then
|
if tun_device_readable; then
|
||||||
echo " 🟢 /dev/net/tun:可读写"
|
echo " 🐱 /dev/net/tun:可读写"
|
||||||
else
|
else
|
||||||
echo " 🚨 /dev/net/tun:存在但不可正常读写"
|
echo " 🚨 /dev/net/tun:存在但不可正常读写"
|
||||||
fi
|
fi
|
||||||
@@ -4057,7 +4048,7 @@ doctor_tun_checks() {
|
|||||||
|
|
||||||
case "$cap_rc" in
|
case "$cap_rc" in
|
||||||
0)
|
0)
|
||||||
echo " 🟢 CAP_NET_ADMIN:已检测到"
|
echo " 🐱 CAP_NET_ADMIN:已检测到"
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
echo " 🚨 CAP_NET_ADMIN:无法精确判断(缺少 capsh)"
|
echo " 🚨 CAP_NET_ADMIN:无法精确判断(缺少 capsh)"
|
||||||
@@ -4068,7 +4059,7 @@ doctor_tun_checks() {
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
if has_ip_command; then
|
if has_ip_command; then
|
||||||
echo " 🟢 ip 命令:可用"
|
echo " 🐱 ip 命令:可用"
|
||||||
else
|
else
|
||||||
echo " 🚨 ip 命令:缺失"
|
echo " 🚨 ip 命令:缺失"
|
||||||
fi
|
fi
|
||||||
@@ -4076,7 +4067,7 @@ doctor_tun_checks() {
|
|||||||
if runtime_config_exists; then
|
if runtime_config_exists; then
|
||||||
dns_listen_value="$("$(yq_bin)" eval '.dns.listen // ""' "$RUNTIME_DIR/config.yaml" 2>/dev/null | head -n 1)"
|
dns_listen_value="$("$(yq_bin)" eval '.dns.listen // ""' "$RUNTIME_DIR/config.yaml" 2>/dev/null | head -n 1)"
|
||||||
if [ -n "${dns_listen_value:-}" ] && [ "$dns_listen_value" != "null" ]; then
|
if [ -n "${dns_listen_value:-}" ] && [ "$dns_listen_value" != "null" ]; then
|
||||||
echo " 🟢 DNS 监听:$dns_listen_value"
|
echo " 🐱 DNS 监听:$dns_listen_value"
|
||||||
else
|
else
|
||||||
echo " 🚨 DNS 监听:未解析到"
|
echo " 🚨 DNS 监听:未解析到"
|
||||||
fi
|
fi
|
||||||
@@ -4100,7 +4091,7 @@ doctor_tun_checks() {
|
|||||||
echo " 🌐 默认路由设备:$route_dev"
|
echo " 🌐 默认路由设备:$route_dev"
|
||||||
case "$route_takeover" in
|
case "$route_takeover" in
|
||||||
yes)
|
yes)
|
||||||
echo " 🟢 默认路由接管:看起来已接管(设备命中 tun/clash/mihomo 特征)"
|
echo " 🐱 默认路由接管:看起来已接管(设备命中 tun/clash/mihomo 特征)"
|
||||||
;;
|
;;
|
||||||
no)
|
no)
|
||||||
echo " 📜 主默认路由:仍指向 $route_dev(仅代表 main table;Linux Tun 可通过 policy routing / rule table 生效)"
|
echo " 📜 主默认路由:仍指向 $route_dev(仅代表 main table;Linux Tun 可通过 policy routing / rule table 生效)"
|
||||||
@@ -4335,13 +4326,13 @@ tun_doctor_log_evidence() {
|
|||||||
traffic_line="$(tun_log_tun_source_line 2>/dev/null || true)"
|
traffic_line="$(tun_log_tun_source_line 2>/dev/null || true)"
|
||||||
|
|
||||||
if [ -n "${adapter_line:-}" ]; then
|
if [ -n "${adapter_line:-}" ]; then
|
||||||
echo " 🟢 Tun adapter 日志:$adapter_line"
|
echo " 🐱 Tun adapter 日志:$adapter_line"
|
||||||
else
|
else
|
||||||
echo " 🚨 Tun adapter 日志:未在 mihomo.out.log 中找到"
|
echo " 🚨 Tun adapter 日志:未在 mihomo.out.log 中找到"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${traffic_line:-}" ]; then
|
if [ -n "${traffic_line:-}" ]; then
|
||||||
echo " 🟢 Tun 流量日志:$traffic_line"
|
echo " 🐱 Tun 流量日志:$traffic_line"
|
||||||
else
|
else
|
||||||
echo " 🚨 Tun 流量日志:未发现 28.0.0.x Tun 源地址流量"
|
echo " 🚨 Tun 流量日志:未发现 28.0.0.x Tun 源地址流量"
|
||||||
fi
|
fi
|
||||||
@@ -4354,13 +4345,13 @@ tun_doctor_policy_evidence() {
|
|||||||
route_line="$(tun_policy_route_line 2>/dev/null || true)"
|
route_line="$(tun_policy_route_line 2>/dev/null || true)"
|
||||||
|
|
||||||
if [ -n "${rule_line:-}" ]; then
|
if [ -n "${rule_line:-}" ]; then
|
||||||
echo " 🟢 Tun policy rule:$rule_line"
|
echo " 🐱 Tun policy rule:$rule_line"
|
||||||
else
|
else
|
||||||
echo " 🚨 Tun policy rule:未发现 lookup 2022 / iif Meta 相关规则"
|
echo " 🚨 Tun policy rule:未发现 lookup 2022 / iif Meta 相关规则"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${route_line:-}" ]; then
|
if [ -n "${route_line:-}" ]; then
|
||||||
echo " 🟢 Tun policy route:$route_line"
|
echo " 🐱 Tun policy route:$route_line"
|
||||||
else
|
else
|
||||||
echo " 🚨 Tun policy route:未发现 table 2022 默认路由指向 Meta/tun 设备"
|
echo " 🚨 Tun policy route:未发现 table 2022 默认路由指向 Meta/tun 设备"
|
||||||
fi
|
fi
|
||||||
@@ -4540,44 +4531,44 @@ tun_doctor_conclusion_line() {
|
|||||||
case "${1:-traffic-check-failed}" in
|
case "${1:-traffic-check-failed}" in
|
||||||
ok)
|
ok)
|
||||||
if tun_has_policy_routing_evidence 2>/dev/null; then
|
if tun_has_policy_routing_evidence 2>/dev/null; then
|
||||||
echo "🟢 最终状态:已生效(Tun + policy routing + 主动流量验证通过)"
|
echo "🐱 最终状态:已生效(Tun + policy routing + 主动流量验证通过)"
|
||||||
else
|
else
|
||||||
echo "🟢 最终状态:已生效(主动流量验证通过)"
|
echo "🐱 最终状态:已生效(主动流量验证通过)"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
policy-routing-likely-effective)
|
policy-routing-likely-effective)
|
||||||
if tun_log_tun_source_line >/dev/null 2>&1; then
|
if tun_log_tun_source_line >/dev/null 2>&1; then
|
||||||
echo "🟢 最终状态:已生效(Tun + policy routing 已安装,并观察到 Tun 源地址流量)"
|
echo "🐱 最终状态:已生效(Tun + policy routing 已安装,并观察到 Tun 源地址流量)"
|
||||||
else
|
else
|
||||||
echo "🟡 最终状态:很可能已生效(Tun + policy routing 已安装;主动流量验证不足 / 未观察到明确 Tun 源地址日志)"
|
echo "🟡 最终状态:很可能已生效(Tun + policy routing 已安装;主动流量验证不足 / 未观察到明确 Tun 源地址日志)"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
missing-cap-net-admin)
|
missing-cap-net-admin)
|
||||||
echo "🔴 Tun 未生效:当前能力检测未通过(CAP_NET_ADMIN)"
|
echo "❗ Tun 未生效:当前能力检测未通过(CAP_NET_ADMIN)"
|
||||||
;;
|
;;
|
||||||
missing-tun-device)
|
missing-tun-device)
|
||||||
echo "🔴 Tun 未生效:缺少 /dev/net/tun"
|
echo "❗ Tun 未生效:缺少 /dev/net/tun"
|
||||||
;;
|
;;
|
||||||
tun-device-not-readable)
|
tun-device-not-readable)
|
||||||
echo "🔴 Tun 未生效:/dev/net/tun 不可读写"
|
echo "❗ Tun 未生效:/dev/net/tun 不可读写"
|
||||||
;;
|
;;
|
||||||
missing-ip-command)
|
missing-ip-command)
|
||||||
echo "🔴 Tun 未生效:缺少 ip 命令"
|
echo "❗ Tun 未生效:缺少 ip 命令"
|
||||||
;;
|
;;
|
||||||
runtime-not-running)
|
runtime-not-running)
|
||||||
echo "🔴 Tun 未生效:代理内核未运行"
|
echo "❗ Tun 未生效:代理内核未运行"
|
||||||
;;
|
;;
|
||||||
controller-unreachable)
|
controller-unreachable)
|
||||||
echo "🔴 Tun 未生效:控制器不可访问"
|
echo "❗ Tun 未生效:控制器不可访问"
|
||||||
;;
|
;;
|
||||||
disabled-in-state|disabled-in-runtime-config)
|
disabled-in-state|disabled-in-runtime-config)
|
||||||
echo "🔴 Tun 未生效:Tun 状态与运行配置不一致"
|
echo "❗ Tun 未生效:Tun 状态与运行配置不一致"
|
||||||
;;
|
;;
|
||||||
tun-disabled)
|
tun-disabled)
|
||||||
echo "🔴 Tun 未生效:Tun 未开启"
|
echo "❗ Tun 未生效:Tun 未开启"
|
||||||
;;
|
;;
|
||||||
host-ip-unavailable|current-ip-unavailable)
|
host-ip-unavailable|current-ip-unavailable)
|
||||||
echo "🔴 Tun 未生效:无法完成公网出口验证"
|
echo "❗ Tun 未生效:无法完成公网出口验证"
|
||||||
;;
|
;;
|
||||||
traffic-same-as-host)
|
traffic-same-as-host)
|
||||||
if tun_log_has_tun_traffic_evidence 2>/dev/null; then
|
if tun_log_has_tun_traffic_evidence 2>/dev/null; then
|
||||||
@@ -5024,21 +5015,21 @@ cmd_use() {
|
|||||||
|
|
||||||
if [ -z "${recommended:-}" ]; then
|
if [ -z "${recommended:-}" ]; then
|
||||||
if [ -n "${active:-}" ]; then
|
if [ -n "${active:-}" ]; then
|
||||||
ui_title "🟢 当前无更优推荐,保持当前"
|
ui_title "🐱 当前无更优推荐,保持当前"
|
||||||
ui_kv "🚩" "当前主订阅" "$active"
|
ui_kv "🚩" "当前主订阅" "$active"
|
||||||
ui_next "clashctl select 选择节点"
|
ui_next "clashctl select 选择节点"
|
||||||
ui_blank
|
ui_blank
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ui_title "🔴 当前没有可推荐的订阅"
|
ui_title "❗ 当前没有可推荐的订阅"
|
||||||
ui_next "clashctl select 选择节点"
|
ui_next "clashctl select 选择节点"
|
||||||
ui_blank
|
ui_blank
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${recommended:-}" = "${active:-}" ]; then
|
if [ "${recommended:-}" = "${active:-}" ]; then
|
||||||
ui_title "🟢 当前已是推荐订阅,无需切换"
|
ui_title "🐱 当前已是推荐订阅,无需切换"
|
||||||
[ -n "${active:-}" ] && ui_kv "📡" "当前主订阅" "$active"
|
[ -n "${active:-}" ] && ui_kv "📡" "当前主订阅" "$active"
|
||||||
ui_next "clashctl select 选择节点"
|
ui_next "clashctl select 选择节点"
|
||||||
ui_blank
|
ui_blank
|
||||||
@@ -5637,6 +5628,7 @@ cmd_proxy() {
|
|||||||
cmd_upgrade() {
|
cmd_upgrade() {
|
||||||
local verbose="false"
|
local verbose="false"
|
||||||
local target_kernel=""
|
local target_kernel=""
|
||||||
|
local current_version target_version actual_version
|
||||||
|
|
||||||
prepare
|
prepare
|
||||||
|
|
||||||
@@ -5656,13 +5648,23 @@ cmd_upgrade() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
[ -n "${target_kernel:-}" ] || target_kernel="$(runtime_kernel_type)"
|
[ -n "${target_kernel:-}" ] || target_kernel="$(runtime_kernel_type)"
|
||||||
|
target_kernel="$(normalize_kernel_type "$target_kernel")"
|
||||||
|
current_version="$(kernel_installed_version_text "$target_kernel")"
|
||||||
|
target_version="$(kernel_target_version "$target_kernel")"
|
||||||
|
|
||||||
ui_title "🚀 正在升级 ${target_kernel} 内核 ..."
|
ui_title "🚀 正在升级 ${target_kernel} 内核 ..."
|
||||||
|
ui_kv "🧩" "升级方式" "升级到当前设定目标版本,不自动追踪官方 latest"
|
||||||
|
ui_kv "📦" "当前版本" "$current_version"
|
||||||
|
ui_kv "🎯" "目标版本" "$target_version"
|
||||||
|
ui_blank
|
||||||
|
|
||||||
upgrade_runtime_kernel "$target_kernel" "$verbose"
|
upgrade_runtime_kernel "$target_kernel" "$verbose"
|
||||||
|
actual_version="$(kernel_installed_version_text "$target_kernel")"
|
||||||
|
|
||||||
ui_title "🟢 内核升级完成"
|
ui_title "🐱 内核升级完成"
|
||||||
ui_kv "🚀" "当前内核" "$(runtime_kernel_type)"
|
ui_kv "🚀" "当前内核" "$(runtime_kernel_type)"
|
||||||
|
ui_kv "🎯" "目标版本" "$target_version"
|
||||||
|
ui_kv "🧪" "实际版本" "$actual_version"
|
||||||
ui_kv "🧩" "影响范围" "仅更新代理内核,不更新项目脚本"
|
ui_kv "🧩" "影响范围" "仅更新代理内核,不更新项目脚本"
|
||||||
ui_next "clashctl status"
|
ui_next "clashctl status"
|
||||||
ui_blank
|
ui_blank
|
||||||
@@ -5693,7 +5695,7 @@ cmd_update() {
|
|||||||
|
|
||||||
update_project_code "$force_mode" "$regenerate_mode"
|
update_project_code "$force_mode" "$regenerate_mode"
|
||||||
|
|
||||||
ui_title "🟢 项目代码已更新"
|
ui_title "🐱 项目代码已更新"
|
||||||
ui_kv "🧩" "影响范围" "脚本、CLI、配置处理逻辑可能已变化"
|
ui_kv "🧩" "影响范围" "脚本、CLI、配置处理逻辑可能已变化"
|
||||||
if [ "$regenerate_mode" = "true" ]; then
|
if [ "$regenerate_mode" = "true" ]; then
|
||||||
ui_kv "🧩" "配置状态" "已重新生成"
|
ui_kv "🧩" "配置状态" "已重新生成"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
: "${CONFIG_DIR:=}"
|
: "${CONFIG_DIR:=}"
|
||||||
: "${RESOURCE_DIR:=}"
|
: "${RESOURCE_DIR:=}"
|
||||||
|
|
||||||
DEFAULT_MIHOMO_VERSION="${MIHOMO_VERSION:-v1.19.21}"
|
DEFAULT_MIHOMO_VERSION="${MIHOMO_VERSION:-v1.19.23}"
|
||||||
DEFAULT_CLASH_VERSION="${CLASH_VERSION:-v1.18.0}"
|
DEFAULT_CLASH_VERSION="${CLASH_VERSION:-v1.18.0}"
|
||||||
DEFAULT_SUBCONVERTER_VERSION="${SUBCONVERTER_VERSION:-v0.9.0}"
|
DEFAULT_SUBCONVERTER_VERSION="${SUBCONVERTER_VERSION:-v0.9.0}"
|
||||||
DEFAULT_YQ_VERSION="${YQ_VERSION:-v4.52.4}"
|
DEFAULT_YQ_VERSION="${YQ_VERSION:-v4.52.4}"
|
||||||
@@ -85,7 +85,7 @@ ui_section() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ui_ok() {
|
ui_ok() {
|
||||||
printf '🟢 %s\n' "$*"
|
printf '🐱 %s\n' "$*"
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_info() {
|
ui_info() {
|
||||||
@@ -97,7 +97,7 @@ ui_warn() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ui_error() {
|
ui_error() {
|
||||||
printf '🔴 %s\n' "$*" >&2
|
printf '❗ %s\n' "$*" >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_next() {
|
ui_next() {
|
||||||
@@ -2589,12 +2589,12 @@ install_runtime_brief_line() {
|
|||||||
|
|
||||||
case "$status_text" in
|
case "$status_text" in
|
||||||
ready)
|
ready)
|
||||||
echo "🟢 当前状态:ready"
|
echo "🐱 当前状态:ready"
|
||||||
echo "🌐 本地代理:http://127.0.0.1:${mixed_port}"
|
echo "🌐 本地代理:http://127.0.0.1:${mixed_port}"
|
||||||
echo "💻 控制台:http://${controller_display:-$controller}/ui"
|
echo "💻 控制台:http://${controller_display:-$controller}/ui"
|
||||||
;;
|
;;
|
||||||
stopped)
|
stopped)
|
||||||
echo "🔴 当前状态:stopped"
|
echo "❗ 当前状态:stopped"
|
||||||
;;
|
;;
|
||||||
verifying)
|
verifying)
|
||||||
echo "🟡 当前状态:verifying"
|
echo "🟡 当前状态:verifying"
|
||||||
@@ -2607,7 +2607,7 @@ install_runtime_brief_line() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
broken)
|
broken)
|
||||||
echo "🔴 当前状态:broken"
|
echo "❗ 当前状态:broken"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "⚪ 当前状态:unknown"
|
echo "⚪ 当前状态:unknown"
|
||||||
|
|||||||
@@ -859,7 +859,7 @@ print_subscription_health_one() {
|
|||||||
|
|
||||||
echo "📡 订阅名称:$name"
|
echo "📡 订阅名称:$name"
|
||||||
echo "🔧 订阅类型:$type_text"
|
echo "🔧 订阅类型:$type_text"
|
||||||
echo "🟢 启用状态:$enabled_text"
|
echo "🐱 启用状态:$enabled_text"
|
||||||
echo "❤️ 健康状态:${status:-unknown}"
|
echo "❤️ 健康状态:${status:-unknown}"
|
||||||
echo "🚨 失败次数:${fail_count:-0}"
|
echo "🚨 失败次数:${fail_count:-0}"
|
||||||
[ -n "${last_success:-}" ] && echo "🕒 最近成功:$last_success"
|
[ -n "${last_success:-}" ] && echo "🕒 最近成功:$last_success"
|
||||||
|
|||||||
+42
-8
@@ -55,6 +55,47 @@ remove_clash_binary() {
|
|||||||
rm -f "$(clash_bin)" 2>/dev/null || true
|
rm -f "$(clash_bin)" 2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kernel_target_version() {
|
||||||
|
local kernel="$1"
|
||||||
|
|
||||||
|
case "$(normalize_kernel_type "$kernel")" in
|
||||||
|
mihomo)
|
||||||
|
echo "${MIHOMO_VERSION:-$DEFAULT_MIHOMO_VERSION}"
|
||||||
|
;;
|
||||||
|
clash)
|
||||||
|
echo "${CLASH_VERSION:-$DEFAULT_CLASH_VERSION}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
kernel_binary_path() {
|
||||||
|
local kernel="$1"
|
||||||
|
|
||||||
|
case "$(normalize_kernel_type "$kernel")" in
|
||||||
|
mihomo)
|
||||||
|
mihomo_bin
|
||||||
|
;;
|
||||||
|
clash)
|
||||||
|
clash_bin
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
kernel_installed_version_text() {
|
||||||
|
local kernel="$1"
|
||||||
|
local bin version_text
|
||||||
|
|
||||||
|
bin="$(kernel_binary_path "$kernel")"
|
||||||
|
if [ ! -x "$bin" ]; then
|
||||||
|
echo "未安装"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
version_text="$("$bin" -v 2>/dev/null | head -n 1 || true)"
|
||||||
|
[ -n "${version_text:-}" ] || version_text="未知"
|
||||||
|
echo "$version_text"
|
||||||
|
}
|
||||||
|
|
||||||
upgrade_runtime_kernel() {
|
upgrade_runtime_kernel() {
|
||||||
local target_kernel="${1:-}"
|
local target_kernel="${1:-}"
|
||||||
local verbose="${2:-false}"
|
local verbose="${2:-false}"
|
||||||
@@ -71,14 +112,7 @@ upgrade_runtime_kernel() {
|
|||||||
if [ "$verbose" = "true" ]; then
|
if [ "$verbose" = "true" ]; then
|
||||||
info "当前架构:$(get_arch)"
|
info "当前架构:$(get_arch)"
|
||||||
info "目标内核:$target_kernel"
|
info "目标内核:$target_kernel"
|
||||||
case "$target_kernel" in
|
info "目标版本:$(kernel_target_version "$target_kernel")"
|
||||||
mihomo)
|
|
||||||
info "目标版本:${MIHOMO_VERSION:-$DEFAULT_MIHOMO_VERSION}"
|
|
||||||
;;
|
|
||||||
clash)
|
|
||||||
info "目标版本:${CLASH_VERSION:-$DEFAULT_CLASH_VERSION}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
case "$target_kernel" in
|
case "$target_kernel" in
|
||||||
|
|||||||
+1
-1
@@ -88,4 +88,4 @@ else
|
|||||||
echo "🧩 保留内容:runtime 数据仍在"
|
echo "🧩 保留内容:runtime 数据仍在"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "🟢 卸载完成"
|
echo "✨ 卸载完成"
|
||||||
|
|||||||
Reference in New Issue
Block a user