Skip to content

Latest commit

 

History

History
160 lines (130 loc) · 7.98 KB

File metadata and controls

160 lines (130 loc) · 7.98 KB

在 Ubuntu / Linux 上使用 cpx

cpx 是一个静态二进制(约 8–9 MB,CGO_ENABLED=0,无运行时依赖),传过去就能用, 不需要 Go、不需要 npm、不需要装一堆东西。

1. 三条命令

# ① 在 Mac 上:按远端架构交叉编译 → scp → 装好 → 远程自检(一条 make 命令)
make push HOST=user@ubuntu

# ② 在 Ubuntu 上:一条命令自证(不需要 codex、不需要登录、不联网)
cpx selftest

# ③ 真实使用(需要 codex 已登录;没装就先 codex login)
cpx exec "把 build.sh 里的死代码删掉"

没有 ssh 直达,手工三步等价:

make release        # → dist/release/cpx-<版本>-linux-<架构>.tar.gz(附 SHA256SUMS)
scp dist/cpx-linux-amd64 user@ubuntu:/tmp/cpx
ssh user@ubuntu 'chmod +x /tmp/cpx && /tmp/cpx install'     # 装到 ~/.local/bin,无需 sudo

cpx install 会打印 PATH 提示与下一步;cpx selftest 会用内置假上游把转发、 turn 归组、模型替换识别、凭证检查全跑一遍并给出结论。两条命令都不碰你的真实审计日志 (自检写在临时目录,可用 --keep 保留)。

2. 可选依赖

依赖 用途 安装
codex CLI 真实使用(cpx 是它的代理层) npm i -g @openai/codex,首次 codex login
tmux cpx tui 的实时状态面板 sudo apt install tmux
libnotify-bin 降级桌面通知(notify_on_mismatch) sudo apt install libnotify-bin

3. 日常命令

cpx doctor                      # 环境自检 + 明确的"下一步"
cpx                             # 交互式 TUI(参数原样透传给 codex)
cpx exec "…"                    # 一次性任务
cpx tui                         # TUI + 下方实时状态面板(tmux 分屏)
cpx report                      # 事后:哪条请求被替换了模型、STATE 格式是否符合预期、第几个 turn
cpx status                      # 当前会话状态块(默认取最新会话;有降级 → 退出码 1)
cpx status --follow --session <id>   # 只看某个会话(tmux 面板用的就是这条)
cpx watch                       # 实时跟读审计日志

4. 与 macOS 的差异(只有三处)

项 macOS Linux
系统代理检测 额外读 scutil --proxy 只认环境变量:export HTTPS_PROXY=…
桌面通知 osascript(自带) notify-send(libnotify-bin;无桌面会话时静默跳过)
cpx tui brew install tmux sudo apt install tmux

其余(审计、报告、凭证、状态文件、退出摘要、loopback NO_PROXY 注入)完全一致。

代理注意:Ubuntu 上如果走 Clash/Mihomo 的"系统代理"(GNOME 设置界面),它不写环境变量, 请在 shell rc 或 systemd unit 里显式导出:

export HTTPS_PROXY=http://127.0.0.1:7890
export HTTP_PROXY=http://127.0.0.1:7890
export NO_PROXY=127.0.0.1,localhost

5. 服务器常驻(可选,systemd)

# ~/.config/systemd/user/cpx.service
[Unit]
Description=CodexProxy
After=network-online.target

[Service]
Environment=CPX_LISTEN=127.0.0.1:8787
Environment=HTTPS_PROXY=http://127.0.0.1:7890
ExecStart=%h/.local/bin/cpx serve
Restart=on-failure

[Install]
WantedBy=default.target
systemctl --user daemon-reload && systemctl --user enable --now cpx
journalctl --user -u cpx -f

cpx serve 只起代理、不拉 codex;把它打印的手动接入命令行加到需要代理的工具上即可。

状态文件按会话隔离(~/.codexproxy/status-<会话>.json),并发会话不会互相覆盖。 listen 默认只允许回环;要在服务器上对外监听必须显式 Environment=CPX_ALLOW_REMOTE=1, 因为那等于把账号借给任何能访问该端口的人。

6. 实测:一条命令跑通真 Ubuntu 容器

e2e/linux/run.sh                  # 需要 docker;默认 ubuntu:24.04

脚本做的事与你的路径完全一致:构建 linux 静态二进制 → 拷进干净容器(等价 scp)→ cpx install → cpx selftest → 完整链路(基于假 codex + 假上游,免登录)。 2026-09-20 实测(Ubuntu 24.04.5 LTS 容器,e2e/linux/run.sh):

== 1/5 构建 linux/arm64 静态二进制 ==
  8.7M /tmp/…/cpx(单文件、全静态)
== 3/5 传入二进制 + cpx install ==
  已安装:/root/.local/bin/cpx
  提示:/root/.local/bin 不在 PATH。两种办法:
    1) cpx install --add-path      # 自动写进 /root/.profile(幂等)
    2) 手工加一行到 /root/.profile:
       export PATH="/root/.local/bin:$PATH"
  已验证可运行:cpx dev
== 4/5 cpx selftest(无需 codex / 登录 / 联网)==
     请求 1 → gpt-6-astra(上游签发新凭证:true · 292 字符)
     请求 2 → gpt-5.6-sol
  会话 s-selftest · 2026-09-20 05:42:43 → 05:42:43 · 2 请求 / 1 turns · 模型 ⚠ 被替换 1 次
  turn 1  05:42:43  2 请求  ⚠ 1 条被替换
    ⚠ #2   05:42:43      0ms  gpt-6-astra → gpt-5.6-sol  [凭证 ✔ 292 字符 3d4d248a]  tier=default  req_selftest_2
  凭证检查: ✔ 合格
    见过的长度: 292 字符×2
    来源: 客户端携带 1 次 / 未携带 1 次 · 上游签发新凭证 1 张 · 客户端带的是上游此前签发的凭证
    最近一张: 3d4d248a · 292 字符 · 客户端携带 · 不到 1 分钟前签发
  ✅ 自检通过:转发、turn 归组、模型替换识别、凭证检查都正常
     自检日志已清理(需要保留时:cpx selftest --keep)
== 5/5 完整链路(假 codex + 假上游)==
  cpx: 本次会话 s-1c745cb6:2 请求 / 1 turns,模型 ⚠ 被替换 1 次(gpt-6-astra → gpt-5.6-sol),凭证 ✔ 合格(见过 292 字符×2);客户端携带 1 次 / 未携带 1 次 · 上游签发新凭证 1 张 · 客户端带的是上游此前签发的凭证
  ⚠ #2   05:42:44     42ms  gpt-6-astra → gpt-5.6-sol  [凭证 ✔ 292 字符(仅长度/前缀合格) 61541f42]  tier=default  req_linux_2
  凭证检查: ✔ 合格
    来源: 客户端携带 1 次 / 未携带 1 次 · 上游签发新凭证 1 张 · 客户端带的是上游此前签发的凭证
    最近一张: 61541f42 · 292 字符 · 客户端携带
  status exit=1(有降级)
  -- cpx tui(tmux 分屏状态面板;面板窗格 2 行,两行结论都在)--
  %0 h=30 cmd=sleep
  --- 附加在 TUI 下方的 cpx 状态面板 ---
    当前 turn 1 · 模型 ✗ · 凭证 292 字符 ✔
    累计 · 模型正确 1 次 / 错误 1 次 · 凭证 292 字符正确 2 次 / 312 字符错误 0 次
  -- 5b 客户端提前断流(读到终局事件就挂断)--
  fake_codex_stream: terminal=True, hung up
  cpx: 本次会话 s-eb2b1bc3:1 请求 / 1 turns,模型 ✔ 没被替换,凭证 ✔ 合格(见过 292 字符×1);客户端携带 0 次 / 未携带 1 次 · 上游签发新凭证 1 张
  ✓ 审计记为 client_closed,不计入转发错误

7. 常见问题

现象 处理
doctor 报 codex 不可用 which codex 确认 PATH(nvm 安装时常见);必要时 export CPX_CODEX_BIN=/path/to/codex
上不通 / 超时 多数是代理:curl -x $HTTPS_PROXY https://chatgpt.com 自测,或 CPX_UPSTREAM_BASE 指向可达端点
没有桌面通知 sudo apt install libnotify-bin;服务器无桌面会话时按设计静默跳过
cpx tui 提示未找到 tmux sudo apt install tmux;或直接 cpx(功能不受影响)
状态面板只看到「累计」一行 你跑的是修复前的旧二进制(v0.1.0 的发布包正是它):每帧多打一个换行,把「当前 turn」顶出 2 行窗格。cpx version 确认 ≥ 0.1.1,然后重装(源码机器 make install,远端 make push HOST=…,或解压新包 ./cpx install);0.1.1 起两行都在,e2e/linux/run.sh 会断言这一点
想换安装目录 cpx install --prefix ~/bin;或 make push HOST=user@ubuntu DIR=bin
审计/状态文件在哪 ~/.codexproxy/audit.jsonl(0600)、~/.codexproxy/status.json,均可用环境变量覆盖