Files
MailUI4Agents/deploy/systemd/zcode.service
JianFeeeee 51789ee72e deploy: 标准目录部署 —— 运行时不再依赖源码目录
用户注意到:「当前 agentmail 是在源码目录部署的,应当改为标准目录部署」。
查证后有三处实证(都不是猜测):

1. ★ **失败通知钩子执行的是仓库里的脚本**
   (`/home/program/agentmail/deploy/service-failure-notify.mjs`,8 处引用:
   4 个 drop-in + zcode/zcode-mail-bridge 单元 + agentmail-failure-flush)。
   仓库一挪/一改名,故障通知就**静默失效** —— 而那条管线正是用来报告服务故障的。
2. **opencode-serve 的 cwd 就是源码目录**(`WorkingDirectory=/home/program/agentmail`)。
3. ★ **仓库里的 `deploy/*.service` 是旧的源码目录版本**(ExecStart 指向
   `/home/program/agentmail/plugins/...`),而机器上的已被改过 —— 也就是说
   **谁跑一次 install.sh 就会把部署退回源码目录**。drop-in 更是只存在于 /etc 里,
   仓库完全没有它们。

## 改动

- **唯一真相**:`deploy/systemd/` 镜像 systemd 目录结构,收进全部单元与 drop-in
  (8 个单元 + 12 个 drop-in),路径全部改到 `/opt`。
- 运行时脚本装到 **`/opt/agentmail/bin/service-failure-notify.mjs`**(自包含,
  无相对导入);`install.sh` 与 `redeploy-gateway.sh` 都会幂等地装它。
- opencode 的 cwd 改为 `/opt/agentmail`(与网关一致),已重启生效
  (`/proc/<pid>/cwd` 已核)。
- 删掉 `deploy/*.service` 的旧副本,避免两个真相。
- dsh 的 `cordis.patch.yml` 注释里的安装示例也改到标准位置(运行时用的是环境变量,
  那条注释是唯一残留)。

## 判据(`deploy/check-deploy-drift.mjs` 新增「标准目录部署」四条 + 自检)

① 任何 unit/drop-in 都不得引用源码目录;② 已安装单元与 `deploy/systemd/` 逐字节一致;
③ 通知脚本在标准位置且可执行;④ 各服务的 cwd/ExecStart 不在源码目录
(homeagent/dsh/zcode 是**别的产品**的标准位置,按白名单放行)。
自检两个样本:引用源码目录的必须红、干净样本必须绿(证明不是恒真)。

顺带修掉一处**真漂移**:仓库里 dsh 的 `dist/index.js` 落后于部署件(改了 src 没重建),
重建后 `check-deploy-drift` 报「四个宿主都在跑当前代码」。

## 复核

- `/etc/systemd/system/` 引用仓库:**0** 个文件;`/opt/agentmail` 下只剩旧二进制/备份里
  的构建路径(Go 嵌的源码路径,无害)与一条注释。
- 四个宿主都在跑当前代码;标准目录四项全绿。
- 全部服务 active,opencode/网关 cwd 均已在安装根下。
2026-09-14 08:38:33 +08:00

49 lines
2.7 KiB
Desktop File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[Unit]
Description=ZCode headless (Xvfb 虚拟屏) —— 供 Web 远控 / 官方中转访问
Documentation=https://zcode.z.ai
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
# 为什么用虚拟屏而不是 --headlessZCode 的 Web 远控web-remote-control
# **桌面端发起**的功能(界面上有 copyLink / 二维码,"Try again from desktop")。
# 它没有对应的命令行开关 —— 我一开始把 `--web-remote-navigation-height`CSS 变量)
# 与 `--remote-debugging-port`Chrome误读成 ZCode 的开关了。
# 所以要让远控可用,就必须真的把桌面应用跑起来,而无头服务器上没有显示 →
# 用 Xvfb 提供一个。
#
# --no-sandboxElectron 以 root 运行时拒绝启用沙箱(会 FATAL 退出)。
# 这是本机的既有取舍(其它服务也以 root 跑),但要知道它降低了渲染进程的隔离。
#
# --remote-debugging-port暴露 CDP用于程序化驱动界面登录、开启远控、
# 截图核对状态),不必依赖 xdotool 之类的坐标点击。
#
# 为什么套一层 dbus-run-sessionElectron 的**单实例 / 深链转发**依赖会话总线,
# 而下面把 DBUS_SESSION_BUS_ADDRESS 设成了 disabled:(无会话总线时的既有噪声)。
# 这里用 dbus-run-session 给本服务单独起一个会话总线 —— 只为该子进程提供,
# **不动系统总线配置**。
#
# 启动命令只在此处定义一次(唯一的 ExecStart。需要改启动方式就改这里
# 不要在 drop-in 里整条重写 —— drop-in 重写会**静默盖住**本行,
# 导致这里的改动不生效(历史上已因此出现过崩溃循环)。
ExecStart=/usr/bin/dbus-run-session -- /usr/bin/xvfb-run -a -s "-screen 0 1600x1000x24" /opt/ZCode/zcode --no-sandbox --disable-gpu --remote-debugging-port=9333
Environment=HOME=/root
# 把 xdg-open 包装放到 PATH 最前:用于抓取 shell.openExternal 的目标 URL
# (无头机上没有浏览器,否则这个信息会丢失,登录链接就拿不到)
Environment=PATH=/root/gotmp/zcodewrap:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Environment=ELECTRON_DISABLE_SECURITY_WARNINGS=1
# 无会话总线时的既有噪声dbus 报错),不影响功能,不因此改系统总线配置
Environment=DBUS_SESSION_BUS_ADDRESS=disabled:
Restart=always
RestartSec=5
# 崩溃可见性:与 AgentMail 其它宿主同款约定(失败要有人知道,不能静默)
ExecStopPost=-/usr/bin/node /opt/agentmail/bin/service-failure-notify.mjs --report --service zcode.service
ExecStartPost=-/usr/bin/node /opt/agentmail/bin/service-failure-notify.mjs --flush --service zcode.service
[Install]
WantedBy=multi-user.target