用 systemd 把 Python 脚本变成开机自启的可靠服务
背景
把一个 Python 脚本丢到服务器上跑,最常见的做法是 nohup python main.py &。当时能跑,但过两天就会发现:机器重启后进程没了、日志散在 nohup.out 里翻不到、脚本半夜挂了没人知道。用 systemd 托管,改造成本其实只有十几行配置。
第一步:写一个 unit 文件
在 /etc/systemd/system/ 下新建 myjob.service:
[Unit]
Description=My Python Job
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/myjob
EnvironmentFile=/opt/myjob/.env
ExecStart=/opt/myjob/.venv/bin/python /opt/myjob/main.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
第二步:加载并启动
两条命令,一条让它被 systemd 认识,一条让它开机自启并立刻跑起来:
systemctl daemon-reload
systemctl enable --now myjob
改完 unit 文件之后一定要重新 daemon-reload,否则 systemd 用的还是内存里的旧配置——这是最容易踩的坑,改了半天发现没生效。
几个关键细节
1. 别用 root 跑。User=appuser 加上最小权限,比出事之后再补救便宜得多。注意 WorkingDirectory 要设成脚本真正的工作目录,否则代码里所有相对路径都会失效。
2. EnvironmentFile 的权限要收紧。把环境变量(数据库密码、API Key)放进 .env,用 EnvironmentFile 引用,然后 chmod 600 并 chown 给运行用户。不要直接把密码写在 unit 文件里,那个文件默认全局可读。
3. Restart 用 always 还是 on-failure。常驻服务用 always,进程不管因为什么退出都会被拉起来;一次性任务用 on-failure,正常退出就结束。RestartSec=5 别省,否则进程因配置错误秒退时会疯狂重启,把 CPU 和日志都打满。
4. 日志交给 journald。不要自己往文件里写,直接打到标准输出,然后 journalctl -u myjob -f 看实时日志,journalctl -u myjob --since "10 min ago" 查历史。想限制体积,在 /etc/systemd/journald.conf 里设 SystemMaxUse=500M。
出问题先看这两个地方
systemctl status myjob 看状态和最近几行输出;journalctl -u myjob -n 50 --no-pager 看完整报错。如果状态是 activating (auto-restart),基本就是脚本启动后立刻退出了,先手动执行一遍 ExecStart 那条命令,报错会直接打在终端上。
小结
systemd 不是什么高级玩意,它只是把「怎么跑、挂了怎么办、日志去哪、重启后还在不在」这四个问题一次性回答完。十几行配置换掉 nohup 和一地鸡毛,这笔账怎么算都划算。
- 点赞
- 收藏
- 关注作者
评论(0)