systemd 托管服务¶
结论¶
把常驻程序交给 systemd,只需一个 unit 文件,崩溃自动拉起、开机自启、日志进 journald:
[Unit]
Description=My Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=myapp
Group=myapp
EnvironmentFile=/etc/default/myapp
ExecStart=/opt/myapp/bin/server --port=${PORT}
Restart=always
RestartSec=5
KillSignal=SIGTERM
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target
为什么用 EnvironmentFile¶
把口令、端口、路径这类会变的东西从 unit 里挪出去:
好处是 unit 文件可以进版本库,敏感值留在服务器上,权限 chmod 600。
注意 systemd 展开变量用 ${VAR}(带花括号),$VAR 会按空格拆词。
常用命令¶
systemctl status myservice # 状态 + 最近日志
journalctl -u myservice -f # 实时日志
journalctl -u myservice --since "10 min ago"
systemctl restart myservice
systemctl disable --now myservice # 停用
排错对照¶
| 现象 | 原因 | 处理 |
|---|---|---|
status=203/EXEC |
路径错或无执行权限 | chmod +x,确认绝对路径 |
status=217/USER |
用户不存在 | useradd --system |
| 启动即退出、日志为空 | 前台进程问题,程序自己 daemon 了 | Type=forking 或让它跑前台 |
| 反复重启 | 配置错 | Restart=always 会让它一直重试,先看 journalctl -u 第一屏 |
| 停止很慢 | 没处理 SIGTERM | 代码里做优雅退出,配合 TimeoutStopSec |
一点加固¶
按程序实际需要取舍,加太狠会导致读不到配置文件。