以前用 nohup 跑服务,重启服务器就没了,进程崩了也没人管。systemd 是 Linux 自带的服务管理器,把这些事一次做完。
写一个 unit 文件
/etc/systemd/system/kb-web.service:
[Unit]
Description=KB Web Service
After=network.target
[Service]
Type=simple
User=www
WorkingDirectory=/www/blog-ai/app
Environment="PYTHONUNBUFFERED=1"
ExecStart=/www/blog-ai/.venv/bin/python -m uvicorn serve:app --host 127.0.0.1 --port 8800
Restart=always
RestartSec=3
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
几个关键项:
WorkingDirectory必须写,否则相对路径(数据库文件、配置文件)全部找错User用非 root,减少被入侵后的影响面Restart=always崩溃自动拉起,RestartSec防止疯狂重启PYTHONUNBUFFERED=1让 print 立即刷到日志,否则缓冲区里的内容看不到
启用
systemctl daemon-reload
systemctl enable --now kb-web
systemctl status kb-web
enable 是开机自启,--now 是立即启动。两个都要,很多人只 start 了,重启机器后发现服务没起来。
看日志
journalctl -u kb-web -f # 实时
journalctl -u kb-web -n 100 # 最近 100 行
journalctl -u kb-web --since "10 min ago"
journalctl -u kb-web -p err # 只看错误
比翻日志文件方便。默认日志会被 journald 轮转,不会把磁盘写满。
环境变量放哪
.env 文件可以用 EnvironmentFile:
EnvironmentFile=-/www/blog-ai/app/.env
前面的 - 表示文件不存在也不报错。注意 EnvironmentFile 的格式是 KEY=value,不能有 export,不能有引号包裹整个值(有些写法会带进变量里)。
.env 权限设成 600,只有服务用户能读。
常见故障
status 显示 failed,日志只有一行退出码:先手动跑一遍 ExecStart 那条命令,通常是路径错或依赖缺失。
改了代码要重启:
systemctl restart kb-web
改了 unit 文件没生效:忘了 daemon-reload。
服务起来但访问 502:多半是监听地址不对。127.0.0.1:8800 只能本机访问,Nginx 反代没问题;如果直接开公网端口,要 0.0.0.0——但不建议,让 Nginx 挡在前面更安全。
为什么不用 supervisor
supervisor 也能做同样的事,但 systemd 是系统自带的,不需要额外装 Python 环境,日志集成到 journalctl,开机自启天然支持。新项目我一律用 systemd。
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://mi-blog.cn/archives/667
共有 0 条评论