跳转至

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
sudo systemctl daemon-reload
sudo systemctl enable --now myservice

为什么用 EnvironmentFile

把口令、端口、路径这类会变的东西从 unit 里挪出去:

# /etc/default/myapp
PORT=8080
SECRET=xxxx

好处是 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

一点加固

NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true

按程序实际需要取舍,加太狠会导致读不到配置文件。