Oamc

用 systemd 托管一个自写服务

本页目录

场景

脚本或程序要开机自启、挂了自动拉起、日志能查。别再写 nohup & 了。

前置条件

  • 程序有确定的启动命令和运行目录
  • 用独立用户跑,不要用 root
  • 知道它会写哪些目录

配置

# 建用户
useradd -r -s /usr/sbin/nologin appuser

# 单元文件
cat >/etc/systemd/system/myapp.service <<'EOF'
[Unit]
Description=My App
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=appuser
Group=appuser
WorkingDirectory=/opt/myapp
Environment="TZ=Asia/Shanghai"
EnvironmentFile=-/opt/myapp/.env
ExecStart=/opt/myapp/venv/bin/python /opt/myapp/main.py
Restart=always
RestartSec=3
LimitNOFILE=65535
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now myapp

验证

systemctl status myapp
journalctl -u myapp -n 100 --no-pager
journalctl -u myapp -f
systemctl restart myapp

杀进程测试自动拉起:

pkill -f main.py && sleep 4 && systemctl is-active myapp

回滚

systemctl disable --now myapp
rm /etc/systemd/system/myapp.service
systemctl daemon-reload

坑

  • 改了 unit 文件必须 daemon-reload,否则 start 还是旧配置。
  • Type=forking 要配 PIDFile,配错会一直 activating。
  • EnvironmentFile 里的值不要加引号外层再加引号,会原样传进去。
  • 程序自己要写日志文件时,注意目录属主是 appuser。
  • Restart=always 遇到配置错误会无限重启,看 journalctl 里的报错再修。
  • 不要用 systemctl edit 之后忘记 daemon-reload,这个坑踩过不止一次。