第 8 章 · 安装部署

安装、使用、长期运行

从 git clone 到"挂着跑一个月"的完整流程。


一、依赖

项要求说明
Python3.9+只用标准库,不装任何包
系统macOS进程与代理检测依赖 ps / lsof / scutil
root不需要全程以普通用户运行
网络出网探测本身就是它的工作

Linux 上核心探测(出口 IP、延迟、DNS 对账、遥测字段)可以跑, 但"读系统代理"和"列进程连接"两块依赖 macOS 的命令,会降级。 移植的入口在 cem/paths.py 和 cem/sockets.py,欢迎提 PR。


二、装

git clone https://github.com/TbusOS/claude-egress-monitor.git
cd claude-egress-monitor

python3 -m cem doctor     # 先看清本机三个入口各走哪条路(不发探测)

doctor 不联网,它只读本机配置。看到三条路径都被识别出来,就说明装好了。

可选:装 mtr 拿路径质量

bash scripts/install-deps.sh

这个脚本只做一件事:用 Homebrew 装 mtr,然后告诉你怎么给它权限。 它不会自己改系统文件权限 —— 那个决定应该由你自己做。

mtr 要发 ICMP 探测包,需要 raw socket,也就是需要 root。两种解法:

# A. 每次手动跑时加 sudo(不改任何系统状态)
sudo mtr --json -n -c 5 -- claude.ai

# B. 给辅助程序 setuid,之后普通用户可直接跑(改了系统文件权限,自己权衡)
sudo chown root $(brew --prefix)/sbin/mtr-packet
sudo chmod u+s $(brew --prefix)/sbin/mtr-packet

本工具默认按普通用户调用 —— 一个监控工具不该要求你用 sudo 跑它自己。 没给权限时路径质量面板显示"未安装/无权限"并给出上面这两条命令, 其余功能完全不受影响。

装好之后,界面「路径质量」那一屏有两个入口:

  • 全部测一遍 —— 把所有 Claude 域名加对照组跑一遍,约一到两分钟。 跑的时候按钮上有 N/M 进度,结果一条一条出。
  • 自动探测(默认关闭)—— 打开之后按 1 / 5 / 15 分钟自己跑。 它有自己的开关和间隔,不跟着主监控走:主采样一轮几百毫秒, 而一遍 mtr 要一两分钟,混在一起会让"每 30 秒一轮"变成谎话。

两个地方会拒测并说明原因,而不是给一个假数字:

  • 目标解析到 fake-ip 占位地址时。硬测会得到一跳、零点几毫秒的漂亮结果, 那是本机分流器自己应答的,和 Claude 无关。
  • 终点一个 ICMP 回包都没有时,报"量不出丢包率"而不是"丢包 100%"。

另外,解析到同一个地址的域名只测一次(并列出共用它的那些域名)—— 七个域名指向同一套 Anycast 前端时,测七遍不会多出任何信息。


三、命令

命令做什么联网
python3 -m cem doctor看清本机三个入口各走哪条路否
python3 -m cem probe立刻采一轮,打印在终端是
python3 -m cem probe --json同上,输出 JSON是
python3 -m cem endpoints打印 Claude 会连的域名清单 + 取证来源否
python3 -m cem telemetry静态提取遥测字段否
python3 -m cem serve起网页界面按需

常用参数:

python3 -m cem probe --all            # 把可选项全打开(含厂商 IP 段、RDAP)
python3 -m cem probe --no-telemetry   # 跳过遥测目的地探测
python3 -m cem probe --no-sockets     # 不列本机连接
python3 -m cem probe --path-quality   # 顺带跑 mtr(慢,要装 mtr)
python3 -m cem telemetry --all-events # 打印全部事件名而不是前几十个

四、网页界面

python3 -m cem serve --open

打开 http://127.0.0.1:8787/。监控默认是关的 —— 一个监控网络流量的工具,不该在你没同意之前就开始发请求。 在页面右上角的开关打开它,采样间隔可选 10 秒 / 30 秒 / 5 分钟。

参数默认说明
--host127.0.0.1只监听回环地址
--port8787
--interval30采样间隔(秒)
--start关起来就开始采(无人值守时用)
--archive./data/days按天归档目录
--no-archive—完全不落盘
--demo关注入虚构数据,一个探测都不发
--open关顺手打开浏览器

不要把它暴露到局域网

界面上有出口 IP、代理端口、本机连接列表和进程名 —— 这些合起来就是"你的网络长什么样"。默认只监听回环地址是刻意的。

真要在另一台机器上看,用 SSH 转发,别改 --host:

ssh -N -L 8787:127.0.0.1:8787 你的用户名@那台机器
# 然后在本地浏览器打开 http://127.0.0.1:8787/

只想看界面长什么样

python3 -m cem serve --demo --open

演示模式注入一轮完全虚构的采样,地址取自 RFC 5737 文档保留段 (192.0.2.0/24、198.51.100.0/24、203.0.113.0/24), 一个探测都不发。界面上会显式标出"演示数据"。


五、长期挂着跑

方式一:tmux(最简单)

tmux new -s cem
python3 -m cem serve --start --interval 300
# Ctrl-b d 退出,随时 tmux attach -t cem 回来

方式二:launchd(开机自启,macOS 原生)

写 ~/Library/LaunchAgents/com.local.cem.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>            <string>com.local.cem</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/bin/python3</string>
    <string>-m</string><string>cem</string>
    <string>serve</string>
    <string>--start</string>
    <string>--interval</string><string>300</string>
  </array>
  <key>WorkingDirectory</key> <string>/绝对路径/claude-egress-monitor</string>
  <key>RunAtLoad</key>        <true/>
  <key>KeepAlive</key>        <true/>
  <key>StandardOutPath</key>  <string>/tmp/cem.log</string>
  <key>StandardErrorPath</key><string>/tmp/cem.err</string>
</dict>
</plist>
launchctl load ~/Library/LaunchAgents/com.local.cem.plist   # 启用
launchctl unload ~/Library/LaunchAgents/com.local.cem.plist # 停用

长期跑请把 --interval 调到 300 秒以上。30 秒是给"正在排查"用的, 挂一个月的话它会白发几十万次请求。


六、数据存在哪、怎么删

data/
├── days/2026-08-15.jsonl   ← 按天一个文件,每轮一条精简记录(约 1 KB)
├── asn-cache.json          ← ASN 查询缓存
└── cloud-ranges.json       ← 厂商官方 IP 段缓存(24 小时)

一整天 5 分钟一轮 ≈ 288 条 ≈ 300 KB。

这些文件全部在 .gitignore 里,因为采样产物就是你的网络长什么样。 提交上去等于把自己的出口、代理端口、内网地址公开。

界面「历史看板」里可以选看哪几天、也可以删掉哪几天。 命令行直接删也行:

rm data/days/2026-08-1*.jsonl     # 删某几天
rm -rf data/                      # 全清(缓存会自己重建)

七、部署这份文档站(GitHub Pages)

docs/ 目录本身就是 Pages 的站点根。章节 HTML 由 Markdown 生成:

python3 scripts/build-docs.py      # docs/*.md → docs/*.html,并生成 demo 页

生成器只用标准库,没有构建工具链。改文档的正确姿势是改 .md, 然后跑一次这个脚本,把生成的 .html 一起提交 —— 这样 Pages 不需要 CI 就能更新。

在自己的 fork 上开 Pages:仓库 Settings → Pages → Source: Deploy from a branch → Branch: main / 目录 /docs。


八、卸载

# 停掉 launchd(如果配过)
launchctl unload ~/Library/LaunchAgents/com.local.cem.plist
rm ~/Library/LaunchAgents/com.local.cem.plist

# 删仓库和数据
rm -rf claude-egress-monitor

# 如果给 mtr 加过 setuid,想还原:
sudo chmod u-s $(brew --prefix)/sbin/mtr-packet
sudo chown $(whoami) $(brew --prefix)/sbin/mtr-packet

工具不写系统配置、不装 CA 证书、不改网络设置、不注册后台服务 (除非你自己配了 launchd)。删掉目录就干净了。


九、跑测试

python3 -m unittest discover -s tests -t . -v

全部离线,不发任何请求 —— 解析器都写成了纯函数,喂固定样本。 改代码前先跑一遍,改完再跑一遍。