Clash 终端工作流进阶:把开启代理、切换节点、查询状态统一成 cx
上一篇文章,我已经把基础的 Clash 终端使用方式打通了:
- 知道了为什么
curl --proxy能通,而普通命令不一定会自动走代理; - 学会了通过 API 查节点、切节点、看出口;
- 也写了
clash-node.sh和clash-select.sh这类小脚本。
但是继续用下去之后,我发现还有一个更实际的问题:
能用是一回事,好不好用是另一回事。
如果每次都要手动做下面这些事:
- 先确认 7890/7891/9090 有没有监听
- 再决定要不要启动 Clash
- 再导出环境变量
- 再测 Google
- 再查当前节点
- 再切换策略组
- 再看出口国家
那终端代理工作流仍然很碎。
所以我又往前走了一步:把这些常用操作统一成一个入口——cx。
这篇文章就记录这套“终端代理工作流”的整理过程,重点是:
- 为什么我不想再手动敲一堆
curl + jq + export - 如何把 Clash 的日常操作统一成一个命令前缀
cx start / on / test / current / list / switch / select / country / off分别负责什么- 为什么这种方式特别适合远程开发、服务器终端、AI 工具安装这类场景
这篇不再重复上一篇里关于代理原理、TUN、基础脚本的内容,而更聚焦于:
如何把这些能力组织成一套真正可长期使用的终端工作流。
关键结论先行
当你把 Clash 的日常操作封装成统一入口(例如 cx)时,重点不在于命令更短,而在于把不同“层级”的状态拆开检查:环境变量层(当前 shell 是否默认走代理)、服务/端口层(7890/7891/9090 是否存在)、控制层(策略组/节点状态),以及验证层(实际出口是否符合预期)。
前置条件
- Clash/Mihomo 服务可用,且本地端口可监听:
7890(HTTP)7891(SOCKS5)9090(external controller / API)
- 你能通过 API 查询
/proxies(并可调用相应更新接口)。 - 你至少具备
curl与jq;如果你使用cx on/off,还需要在当前 shell 中能执行对应函数/脚本。
可复现步骤(建议顺序)
cx start:确保服务启动与端口就绪。cx on:为当前 shell 设置代理环境变量。cx test:用同一套验证动作确认代理链路可用。cx current+cx country:确认当前策略选择与实际出口。- 需要变更时使用
cx select/cx switch。 - 当前 shell 不再需要默认走代理时执行
cx off;不需要服务时执行cx stop。
常见误解与纠正(本文后续关联)
如果你观察到“关了当前 shell 的代理(cx off)但端口/节点查询仍可用”,通常是层级差异导致的现象;更彻底的关闭需要停服务(例如 cx stop)。
一、为什么我需要一个统一入口
在终端里使用 Clash,单个动作其实都不难。
例如:
查看监听端口
1 | ss -lntp | grep -E '7890|7891|9090' |
导出代理环境变量
1 | export http_proxy=http://127.0.0.1:7890 |
查看当前节点
1 | curl -s http://127.0.0.1:9090/proxies | jq -r '.proxies["🔰 选择节点"].now' |
查看当前出口国家
1 | curl -s --proxy http://127.0.0.1:7890 https://api.ip.sb/geoip | jq |
切换节点
1 | curl -s -X PUT 'http://127.0.0.1:9090/proxies/...' -H 'Content-Type: application/json' -d '{"name":"🇺🇲 美国Z02"}' |
这些命令都能工作,但问题是:
- 太散
- 太长
- 不适合频繁操作
- 不利于记忆
- 一旦环境变量、策略组、端口、路径稍有变化,就得重新改
所以我想要的不是“再记住几条命令”,而是:
给 Clash 终端工作流做一个统一的人机接口。
于是我把所有常用操作都归到 cx 下面。
二、我最后整理出来的工作流目标
我希望做到的是:
- 在任意目录里都能用
- 不需要每次去记原始 API 路径
- 不需要手动敲
curl + jq - 节点切换要尽量低成本
- 既能管当前 shell 代理,又能管 Clash 后台服务
- 能快速判断“到底是环境变量问题、端口问题,还是节点问题”
最后我整理出的目标命令集大概是这样:
1 | cx start |
这套命令如果能跑通,终端代理这件事基本就从“能用”变成“好用”了。
验证方式对照(按层定位)
| 需要确认的点 | 建议命令 | 关注点 |
|---|---|---|
| 服务是否在运行 | cx ports 或 cx start |
7890/7891/9090 是否在监听 |
| 当前 shell 是否默认走代理 | cx on/off(也可结合 `env |
grep -i proxy`) |
| 代理链路是否可用、出口是否正常 | cx test |
用代理发请求并解析出口信息 |
| 策略层选择与出口是否一致 | cx current + cx country |
/proxies 的 now 与出口 IP/国家等是否匹配 |
flowchart TD
ShellLayer["Shell环境变量层(cx on/off)"] -->|"决定默认代理是否生效"| ShellState["默认走不走代理"]
ServiceLayer["服务/端口层(cx start/stop/ports)"] -->|"决定端口是否存在"| ServiceState["7890/7891/9090是否可用"]
ControlLayer["控制层/API(/proxies)"] -->|"cx current/list/switch/select"| ControlState["节点/策略选择结果"]
ShellState --> ValidationLayer["验证层(cx test/country)"]
ServiceState --> ValidationLayer
ControlState --> ValidationLayer
ValidationLayer --> Outcome["出口与请求是否符合预期"]
三、cx 这套工作流到底解决了什么问题
0. 两层实现思路(底层脚本 + shell 函数)
很多人把“能切节点、能测连通”理解为同一件事,但在终端里做长期工作流时,往往更需要把职责拆开:
- 底层执行逻辑:负责检查本地监听端口、启动/停止 Clash/Mihomo、访问 external controller 的 API(如
/proxies)、以及执行连通性/出口验证。 - shell 入口函数(例如在
~/.bashrc里定义cx()):提供统一的人机接口;其中cx on/off主要完成当前 shell 的环境变量设置/清理,其余命令把请求转交给底层执行逻辑。
这种分层方式的直接收益是:当出现“某一步看起来没生效”时,可以更快定位到底是环境变量层、服务/端口层,还是策略/API 层的问题。
1. 解决“启动”和“开代理”是两回事
以前常见的误区是:
- 以为
export http_proxy=...就等于代理已经启动 - 或者以为 Clash 启动了,终端就会自动走代理
后来我专门把这两层拆开:
cx start
只负责启动 Clash/Mihomo 后台服务,确认 7890/7891/9090 在监听。
cx on
只负责给当前 shell 设置代理环境变量,让这个终端默认走代理。
也就是说,正确顺序变成了:
1 | cx start |
这样逻辑上清晰很多。
2. 解决“代理到底有没有生效”难以判断的问题
很多时候我们说“代理没生效”,其实根本没说明白是哪一层没生效。
所以我把验证动作统一成:
1 | cx test |
它会同时检查:
- 当前 shell 环境变量是什么
- 本地 7890/7891/9090 是否在监听
- 通过 7890 发请求能否成功访问 Google
- 当前出口 IP 是什么
这就让原本分散的排查动作,一下收敛成了一个入口。
3. 解决“节点切换太麻烦”的问题
原始 API 切换方式没问题,但手感很差。
我当时最烦的地方有两个:
- 节点名称必须写完整,包括国旗和空格
- 节点一多,就很容易输错
所以我把它拆成三种使用方式:
查看当前节点
1 | cx current |
列出所有节点
1 | cx list |
按关键词切换
1 | cx switch "美国Z02" |
交互式编号切换
1 | cx select |
其中 cx select 是我经常使用的方式,它更接近“菜单式操作”。
四、这套工作流的完整使用顺序
我现在基本固定成下面这个顺序。
flowchart TD
A["cx start"] --> B["cx on"]
B --> C["cx test"]
C --> D["cx current"]
D --> E["cx select/switch"]
E --> F["cx country"]
F --> G["cx off"]
G --> H["cx stop"]
1. 开始工作前:确认服务起来了
1 | cx start |
这一步的目标不是“开代理”,而是确认:
- Clash 进程存在
- 7890/7891/9090 真在监听
- 日志没有明显报错
如果需要,我还会补一句:
1 | cx ports |
2. 给当前终端开启默认代理
1 | cx on |
这一步之后,当前 shell 里的很多命令都会默认走代理,例如:
1 | curl -I https://www.google.com |
这一步只影响当前终端,不影响别的终端窗口。
3. 立刻做一次连通性确认
1 | cx test |
建议把这一步作为日常动作使用,因为它可以用于判断:
- 端口在不在
- 环境变量在不在
- Google 通不通
- 出口 IP 是什么
很多“我感觉代理没开”的误判,都是因为缺了这个统一测试动作。
4. 看当前出口到底走哪
1 | cx current |
这两个命令组合后,可以更快确认当前选择与实际出口。
cx current告诉你策略组现在选中了哪个节点cx country告诉你这个节点实际的出口国家、地区、IP、组织
这一步特别适合防止“节点名字和实际出口不一致”的情况。
5. 如果当前节点不满意,就切换
快速模糊切换
1 | cx switch "日本Z02" |
交互式切换
1 | cx select |
节点较多时,我更倾向于使用 cx select。
切完之后,一般再补一句:
1 | cx current |
确保真的切到了想要的出口。
6. 不需要当前终端默认代理时,关掉环境变量
1 | cx off |
这一步只影响当前 shell 默认代理,不会把 Clash 后台服务停掉。
7. 真正不需要 Clash 时,再停服务
1 | cx stop |
这时端口才会真的消失。
五、cx 这套工作流常见的价值
1. 它把“代理是一组状态”这件事讲清楚了
以前终端里用 Clash,最容易混淆的是三件事:
- 当前 shell 有没有默认代理环境变量
- Clash 后台服务有没有启动
- 当前策略组到底选了哪个节点
这三件事本来就在不同层:
- shell 层
- 服务层
- API/策略层
cx 的好处就是把它们拆开了:
cx on / off管 shellcx start / stop / ports管服务cx current / list / switch / select管策略cx test / country管验证
这样一拆,日常使用就清爽很多。
2. 它特别适合服务器场景
如果你是在本地桌面上用图形客户端,很多动作可以点鼠标完成。
但在 Linux 服务器、Remote-SSH、远程开发环境里,你需要的是:
- 纯终端
- 低依赖
- 可脚本化
- 可重复执行
- 尽量少记忆复杂命令
这就是为什么我觉得 cx 这种统一入口,在服务器上特别有价值。
3. 它让“排查问题”也统一了
以前排查一个代理问题,可能要连续做这些动作:
1 | ss -lntp | grep ... |
现在大多数情况下我只要先跑:
1 | cx ports |
就能很快判断出问题大概在哪一层。
六、cx 这套工作流特别适合什么场景
在长期使用后,我发现它适用于下面这些场景:
1. AI 工具安装与登录前的环境准备
例如:
- Claude Code
- Codex CLI
- npm 全局工具
- pip 安装包
- GitHub 拉取代码
这些操作依赖你是否能稳定让当前终端走代理。
2. 远程 SSH / VS Code Remote-SSH
这种场景下,图形化代理客户端的作用相对有限,通常还需要靠终端里的代理控制。
3. 节点很多,需要频繁切换出口
尤其是:
- 日本 / 美国 / 香港 / 新加坡
- 有 IEPL、下载专用、低倍率节点
- 需要快速试不同节点效果
这时候 cx list + cx select + cx country 的组合更省事。
4. 想做长期维护,而不是临时拼凑几条命令
一旦你开始长期用服务器,代理这件事就不该还是靠零散命令维持。
七、我常用的一组命令
如果只保留常用的一组,我现在基本就记这几个:
1 | cx start |
大多数日常使用都能覆盖到。
如果再缩成“最小日常工作流”,就是:
1 | cx start |
八、我对这套工作流的一个总结
前一篇文章更多是在回答:
Clash 在 Linux 上到底怎么用顺?
而这一篇更像是在回答:
当这些基础动作都能跑通之后,怎么把它们整理成一套真正可长期使用的终端习惯?
对我来说,cx 的主要意义不是“又发明了一个命令缩写”,而是:
把 Clash 在 Linux 终端里的日常使用整理成了一套一致且便于维护的工作流。
它的价值主要在于三点:
- 把原本分散的命令统一到一个入口
- 把“启动、开代理、切节点、测试、验证”串成一个自然流程
- 让以后每次新开终端、新上服务器时,都能迅速恢复到熟悉的节奏
总结
如果你也在 Linux 服务器、远程开发、AI 工具安装、GitHub 访问、节点切换这些场景下长期使用 Clash,我很建议你不要只停留在“会敲几条命令”的阶段,而是把这些动作沉淀成一套自己的工作流。
对我来说,这套工作流最终就收敛成了一个前缀:
1 | cx |
看起来很小,但它背后其实把:
- 当前 shell 代理
- Clash 后台服务
- 本地 API
- 节点管理
- 出口验证
全部串了起来。
当这些动作都被统一之后,终端代理这件事就不再是“麻烦但不得不做的前置准备”,而会慢慢变成一种很自然的基础设施能力。




