华为云 ECS 上用 systemd 托管 Node 服务:六个容易踩的坑
把 Node 服务丢进 systemd 托管,是 ECS 上最省事也最容易翻车的一步。我拿一台华为云 ECS 做验证,把一个 Express 服务从 nohup 迁到 systemd,前后踩了六个坑,记下来给同样在做迁移的人省点时间。
一、ExecStart 要用绝对路径
systemd 不加载 .bashrc,也不读 /etc/profile,用 nvm 装的 node 在 unit 里直接写 node 会报找不到命令。把路径写死:ExecStart=/usr/bin/node /opt/app/server.js。先用 which node 确认实际路径,版本管理工具装的就指到那个版本的具体路径,别在 unit 里 source 环境脚本。
二、运行用户和工作目录都要显式写
不加 User 就是以 root 跑,出问题就是大问题。补上 User=app、Group=app,并把代码目录属主改对。同时一定要写 WorkingDirectory=/opt/app,否则进程的工作目录是根目录,代码里读 .env、读模板、读静态资源的相对路径会全部失败。这类错误日志里看不出原因,排查成本最高。
三、配置和密钥别写进 unit
Environment=KEY=value 直接写在 unit 里,等于把密钥明文留在 /etc/systemd/system,权限还常常是 644。改成 EnvironmentFile=/etc/app.env,再 chmod 600、属主 root,服务以 app 用户运行时按需授权。至少别让密钥跟着 unit 文件一起被复制到别处。
四、Restart 配不好就是重启风暴
Restart=always 很常见,但没有 RestartSec 和启动频率限制就是灾难:配置错了进程秒退,systemd 每秒拉起一次,日志被刷屏,机器负载飙升。建议 Restart=on-failure、RestartSec=5,再配 StartLimitIntervalSec=60 与 StartLimitBurst=5,连续失败五次就停下,留出看日志的时间。
五、优雅退出靠信号,不靠猜
systemctl stop 默认先发 SIGTERM,等 TimeoutStopSec(默认 90 秒)才 SIGKILL。代码里不监听 SIGTERM,进程就被硬杀,正在处理的请求直接断。在 Node 里加 process.on 监听 SIGTERM,回调里 server.close() 并关闭数据库连接,再把 TimeoutStopSec 调到 30 秒左右,滚动重启才不会掉请求。
六、日志交给 journald
StandardOutput=journal、StandardError=journal,之后 journalctl -u app -f 看实时日志,--since 查历史,不用再维护一份 rotatelogs。要接外部采集就加 SyslogIdentifier=app,按标识过滤更省事。
最后
改完 unit 记得 systemctl daemon-reload,再 enable --now。六条里最容易被忽视的是第二条 WorkingDirectory,我在这上面耗的时间比其余五条加起来还多。
- 点赞
- 收藏
- 关注作者
评论(0)