现代 Linux 服务优先由 systemd 管理。Supervisord 适合管理部分前台进程,但不应与 systemd 重复托管同一个服务。
## Systemd 常用操作
```bash
systemctl status app.service
systemctl start app.service
systemctl stop app.service
systemctl restart app.service
systemctl reload app.service
systemctl enable --now app.service
systemctl is-active app.service
journalctl -u app.service -b --since '30 min ago'
```
示例 Unit:
```ini
[Unit]
Description=Example Application
After=network-online.target
Wants=network-online.target
[Service]
User=app
Group=app
WorkingDirectory=/opt/app
ExecStart=/opt/app/bin/server
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
```
修改后执行 systemctl daemon-reload,再重启并检查日志。脚本不要自行 fork,除非 Unit 的 Type 与程序行为匹配。
## 优雅停止
服务必须在 SIGTERM 后停止接收新请求、完成或转移在途任务、关闭连接并在超时前退出。systemd 的 TimeoutStopSec 不是越短越好;设置过短会导致 SIGKILL 和数据损坏。
## Supervisord
适用于遗留应用或一个受控环境中的多进程管理:
```ini
[program:worker]
command=/opt/app/bin/worker
user=app
directory=/opt/app
autostart=true
autorestart=unexpected
stdout_logfile=/var/log/app/worker.log
stderr_logfile=/var/log/app/worker.err.log
stopasgroup=true
killasgroup=true
```
用 supervisorctl status、reread、update 和 restart 管理。顶层仍可让 systemd 托管 supervisord,但不要再让 systemd直接管理同一个 worker。
## 排障顺序
1. 查看 status 中的退出码和最近日志。
2. 检查 ExecStart、用户、目录、环境变量和文件权限。
3. 确认依赖、端口和配置语法。
4. 查看是否触发启动频率限制或 OOM。
5. 手工以服务账号运行前台命令复现。
6. 修复后验证启动、停止、重启和开机自启。
不要把 Secret 直接写入 Unit 的 Environment 行,因为可能被进程信息或配置读取。使用权限受控的 EnvironmentFile 或专用 Secret 系统。