在终端里手动跑起来的进程,你一关终端它就没了。 要它一直活着,得交给系统的服务管理器。 这一篇讲怎么交、以及一条比技术更重要的纪律:自动重启掩盖问题。
本文写什么服务化的三个收益、两条路径的取舍、必踩的坑、重启纪律。 本文不写我们自己的服务名、单元文件与日志位置。示例全是通用占位。
| 收益 | 没有它会怎样 |
|---|---|
| 开机自启 | 机器重启(云厂商维护、内核更新)之后,你的东西再也没起来,而且没人告诉你 |
| 崩了重拉 | 一次偶发崩溃就等于永久停止 |
| 日志有去处 | 输出散在某个终端里,关了就没了;出事时无从查起 |
| 统一的起停查 | 每个服务一套自己的启动方式,三个月后你自己都记不住 |
第一条最容易被低估:云上的机器一定会重启。 不是「可能」——宿主维护、内核补丁、你自己手滑,一年总会有几次。
| 工具自带的安装命令 | 自己写服务单元 | |
|---|---|---|
| 怎么做 | 比如 hermes gateway install(加 --system 装成开机自启的系统服务) | 手写一份单元文件 |
| 好处 | 它知道自己需要什么环境——路径、变量、依赖顺序 | 完全可控 |
| 坏处 | 你不知道它替你写了什么 | 容易漏掉环境(见下) |
| 建议 | 有就先用它 | 没有、或者要改行为时再写 |
Hermes 的文档明确警告:不要加 ExecStopPost=/bin/kill -9 这类 drop-in,
会造成无限重启循环。
更一般的教训:一个自带进程管理的服务,不要再套一层你自己的进程管理。 两层互相打架的典型症状是「它一直在重启,但日志里看不出为什么」—— 因为每次还没来得及写清楚就被杀了。
和定时任务那个坑是同一件事:
服务跑起来的环境是极简的——PATH 短、没有你 shell 配置里的变量、
工作目录也不是你以为的那个。
症状:手动跑好好的,装成服务就「找不到命令」或「找不到配置」。 解法一样:绝对路径、显式设变量、显式设工作目录。
| 用户级 | 系统级 | |
|---|---|---|
| 权限 | 跟着那个用户走,更小 | 更大 |
| 开机自启 | ⚠ 通常要额外开一个开关,否则要等那个用户登录才起 | 开机就起 |
| 建议 | 默认选这个——最小权限原则 | 确实需要开机即起、或要绑低端口时 |
用户级服务默认只在该用户登录后才启动。你把机器重启一遍会发现服务没起来—— 但你 SSH 进去一看,它又起来了(因为你刚登录)。这个假象很容易骗过验证。
验证方法要严一点:重启机器,然后不登录,从外部确认服务在响应。
服务每 30 秒崩一次、每 30 秒被拉起来一次——从外面看它一直是「active」。 你可能几个月都不知道。
而这几个月里它做了什么?可能每次重启都丢掉正在处理的东西、 可能重复执行了本该只做一次的动作、可能一直在烧钱重试。
两条纪律:
① 重启次数本身要被监控——不是「它活着吗」,是「它这一天重启了几次」;
② 设重启上限:短时间内连续失败超过 N 次就停下别再拉,
让它明确地死掉。一个明确死掉的服务比一个假装活着的服务好得多。
| 做 | 为什么 |
|---|---|
| 交给系统日志,或写到固定文件 | 要有个确定的地方能查 |
| 配轮转与大小上限 | 否则迟早把盘写满(第 19 篇) |
| 别把密钥打进日志 | 日志通常权限更松、还会被备份走。这是很常见的泄漏路径 |
hermes gateway install(用户级)、
sudo hermes gateway install --system(系统级、开机自启)、
hermes gateway start / stop / status;macOS 生成 launchd plist。
官方明确警告不要添加 ExecStopPost=/bin/kill -9 之类的 drop-in(无限重启)。
官方文档,2026-08-21 核。