华为云 ECS 上用 systemd 托管 Node 服务:六个容易踩的坑

举报
yd_243895892 发表于 2026/11/01 14:46:48 2026/11/01
【摘要】 把 Express 服务从 nohup 迁到 systemd 时踩过的六个坑:ExecStart 写绝对路径、运行用户与工作目录、密钥放 EnvironmentFile、Restart 加频率限制防重启风暴、监听 SIGTERM 优雅退出、日志交给 journald,每条都附了可直接抄的配置写法。

把 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,我在这上面耗的时间比其余五条加起来还多。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。