kita / notes

约 2 分钟

手动启动的服务,重启机器就没了

网易云点歌那个功能,隔一阵子就不好使。不是完全挂掉,是"有时候能用有时候不能用"。

一开始我怀疑是插件那边的问题,后来才想到去看服务器上那个 API 服务本身。

手动起的进程

这个 API 是 NeteaseCloudMusicApiEnhanced,装在 /root/api-enhanced 下。当初的启动方式很朴素:

cd /root/api-enhanced
node app.js

手动跑在前台,没有 systemd 也没有 docker 托管。 这意味着三件事:

  • 服务器重启,它不会自己起来
  • 终端一关,进程可能跟着走
  • 进程真挂了,没有任何机制把它拉起来

"有时候不能用"就是这个原因——它对运行环境的连续性完全没有保障。

先确认现状

动手之前先看清楚它是怎么跑着的:

ps -eo pid,etimes,cmd | grep app.js

看到了 node 进程,说明当时是活的。再看有没有被托管:

ls /etc/systemd/system/*.service

里面没有它。到这一步就确定了:问题不在代码,在于它压根没有被人管。

补一个 unit

解决办法是给它写个 systemd unit,文件放 /etc/systemd/system/ncm-api-enhanced.service:

[Unit]
Description=NeteaseCloudMusicApiEnhanced (ncm-api)
Documentation=file:///root/api-enhanced/README.md
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=60
StartLimitBurst=10

[Service]
Type=simple
User=root
WorkingDirectory=/root/api-enhanced
ExecStart=/usr/bin/node app.js
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=ncm-api

[Install]
WantedBy=multi-user.target

几个地方是特意写的:

After=network-online.target + Wants= —— 这个服务要对外提供 HTTP,得等网络真的可用再起。只写 After=network.target 有时候起太早,监听会失败。

Restart=always + RestartSec=5 —— 挂了就拉起来,隔 5 秒。这是"自动恢复"的核心。

StartLimitIntervalSec + StartLimitBurst —— 这两个是配套的限流。如果服务有严重的启动错误,Restart=always 会让它无限重启,日志瞬间被刷爆。加上"60 秒内最多重启 10 次",超过就停手,留出时间给人看日志。

SyslogIdentifier=ncm-api —— 加了它之后 journalctl -u 出来的日志每行都带这个标识,和别的服务混在一起时好认。

启用并验证

systemctl daemon-reload
systemctl enable --now ncm-api-enhanced

enable 是设开机自启,--now 是顺便立刻起来。

验证的一个技巧是看重启次数:

systemctl show ncm-api-enhanced -p ActiveState,SubState,NRestarts
ActiveState=active
SubState=running
NRestarts=0

NRestarts=0 说明它一直是稳的,没靠重启策略硬撑。如果这个数字一直在涨,那说明服务本身有崩的问题,得回去看日志。

同一个毛病还不止一个

改完之后我把服务器上所有"手动起的东西"过了一遍,发现同样的坑还躺着好几个:

arcaea-server.service      自建查分后端
course-sync.service        课表同步 Web 服务
dsh-web.service            DSH 网页版
dsh-bridge.service         DSH 给 AstrBot 用的转发
kita-blog.service          这个博客

这些现在都是 enabled 状态。判断标准很简单:现在还在跑的东西,如果它不在 systemctl list-units 里,那它下次重启就会消失。

那台服务器上还跑着 docker 里的 astrbot、napcat、postgres,那些有 restart 策略管着,不用我操心。真正容易漏的就是这种"当初在终端里敲了一行命令"起起来的服务——它能一直跑到你重启为止,让你以为它很稳定。

← 回到全部笔记