公司博客 // 2026-07-14 · BY IDCBOT

systemd服务怎么写?让程序开机自启、崩溃自动重启完整教程

写了个Python脚本、部署了个Bot或Web应用,怎么让它开机自动启动、崩溃了自动拉起、还能方便地管理和看日志?答案不是nohup也不是screen,而是systemd服务。这是Linux下托管长期运行程序的标准做法。本文教你写出规范的systemd服务。

一、为什么用systemd,而不是nohup/screen?

nohup和screen能让程序在后台跑,但有硬伤:服务器重启后不会自动恢复、程序崩溃了不会自动重启、日志管理混乱。systemd解决了这一切:

  • 开机自启:服务器重启,你的程序自动回来;
  • 崩溃自愈:程序挂了自动重启,大幅提升可用性;
  • 统一管理:start/stop/restart/status一套命令;
  • 日志集成:journalctl统一查看日志。

二、写一个systemd服务文件

在 /etc/systemd/system/ 下创建服务文件,比如 mybot.service:

[Unit]
Description=My Python Bot
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/mybot
ExecStart=/opt/mybot/venv/bin/python /opt/mybot/bot.py
Restart=always
RestartSec=5
User=www-data

[Install]
WantedBy=multi-user.target

关键字段解释:

  • After=network.target:等网络就绪再启动(联网程序必加);
  • WorkingDirectory:程序工作目录;
  • ExecStart:启动命令,必须用绝对路径(常见坑);
  • Restart=always:崩溃后总是重启(核心的自愈能力);
  • RestartSec=5:重启前等5秒,避免疯狂重启;
  • User:用哪个用户运行(安全起见别用root跑业务)。

三、启用和管理服务

systemctl daemon-reload        # 改动服务文件后必须reload
systemctl enable mybot         # 设置开机自启
systemctl start mybot          # 启动
systemctl status mybot         # 查看状态(排错第一步)
systemctl restart mybot        # 重启
systemctl stop mybot           # 停止

enable --now 可以一步完成”设为自启+立即启动”。

四、查看日志

journalctl -u mybot            # 查看该服务所有日志
journalctl -u mybot -f         # 实时滚动(排故障用)
journalctl -u mybot --since "1 hour ago"   # 看最近1小时
journalctl -u mybot -n 100     # 看最后100行

程序的print输出、错误信息都会被systemd收集,journalctl统一查看,比自己管理日志文件方便得多。

五、进阶配置

  • 环境变量:用 Environment="KEY=value" 或 EnvironmentFile= 加载环境变量(敏感信息如Token放这里,别硬编码);
  • 资源限制:MemoryLimit=、CPUQuota= 限制服务的资源占用,防止单个服务吃垮机器;
  • 依赖关系:用 Requires=、After= 声明服务启动顺序(如应用依赖数据库先启动)。

六、常见排错

  • 服务启动失败:先看 systemctl status 和 journalctl -u,错误几乎都写在里面;
  • ExecStart路径错:用绝对路径,虚拟环境要指向venv里的解释器;
  • 权限问题:User指定的用户对WorkingDirectory要有权限;
  • 改了不生效:忘了 daemon-reload。

结论

systemd是让程序”专业地跑起来”的标准方式:开机自启、崩溃自愈、统一管理、日志集成。无论是TG Bot、Web应用、还是自定义脚本,都值得花五分钟写个service文件托管起来。在你的香港VPS上把你的第一个程序做成systemd服务,从此不再担心它半夜悄悄挂掉没人管。

// LEAVE A COMMENT

Your email address will not be published. Required fields are marked *