用 systemd 托管一个 Node 服务
最小可用的 unit
/etc/systemd/system/myapp.service:
[Unit]
Description=My App
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/app
ExecStart=/usr/bin/node /home/ubuntu/app/server.js
Restart=on-failure
RestartSec=3
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
然后:
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
journalctl -u myapp -f
三个最容易踩的坑
1. ExecStart 必须用绝对路径。 systemd 不读你的 shell 配置,node 这种裸命令大概率找不到 —— 尤其是通过 nvm 装的 Node,路径在 ~/.nvm/versions/node/vX/bin/node。用 which node 查出来写全。
2. WorkingDirectory 不写会出问题。 代码里用相对路径读配置、写日志,都会相对于 / 而不是项目目录,表现为"手动跑正常、服务起来就报文件找不到"。
3. 环境变量不在 .bashrc 里。 服务不会加载你的 shell 环境。敏感变量用单独文件:
EnvironmentFile=/home/ubuntu/app/.env
并确保该文件权限是 600、属主是运行用户。
和 pm2 怎么选
| systemd | pm2 | |
|---|---|---|
| 安装 | 系统自带 | 需要 npm 装 |
| 日志 | journald,统一 | 自己管文件 |
| 开机自启 | 原生 | 要额外 pm2 startup |
| 多进程/负载均衡 | 要配多个 unit | 内置 cluster |
| 适合 | 单机单服务、简单可靠 | 多实例、需要面板 |
单机跑一两个服务,systemd 更省心 —— 少一个需要自己维护的守护进程。
改完之后
改 .service 文件后必须 daemon-reload,否则改动不生效。这一点和 nginx/caddy 改配置要 reload 是同一个道理,但 systemd 不会提示你。
本文为个人学习记录,可能存在错误或已过时,仅供参考。
← 返回笔记列表