systemd 服务管理实战:把一个脚本变成开机自启、崩溃自拉起的后台服务

举报
yd_281047095 发表于 2026/11/01 12:30:25 2026/11/01
【摘要】 很多人在服务器上跑程序还停留在 nohup ./app & 的阶段:SSH 一断还好,机器一重启服务就没了,进程挂了也没人知道。

很多人在服务器上跑程序还停留在 nohup ./app & 的阶段:SSH 一断还好,机器一重启服务就没了,进程挂了也没人知道。其实现代 Linux 发行版自带的 systemd 就能把这些事情一次性解决。本文用一个最小例子,带你从零写一个 systemd 服务单元,并整理日常排障最常用的命令。

一、准备一个要托管的程序

假设我们有一个简单的 Python HTTP 服务,放在 /opt/demo/app.py:

from http.server import HTTPServer, SimpleHTTPRequestHandler
HTTPServer(("0.0.0.0", 8000), SimpleHTTPRequestHandler).serve_forever()

建议为服务单独建一个低权限用户,不要直接用 root 跑:

sudo useradd -r -s /usr/sbin/nologin demo
sudo chown -R demo:demo /opt/demo

二、编写服务单元文件

在 /etc/systemd/system/demo.service 写入:

[Unit]
Description=Demo HTTP Service
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=demo
WorkingDirectory=/opt/demo
ExecStart=/usr/bin/python3 /opt/demo/app.py
Restart=on-failure
RestartSec=5
Environment=APP_ENV=prod

[Install]
WantedBy=multi-user.target

几个关键字段说明:

  • After / Wants:保证网络就绪后再启动,避免监听失败。
  • Type=simple:程序在前台运行即可,不要自己再 fork 到后台。
  • Restart=on-failure:进程异常退出时自动拉起,RestartSec 控制间隔。
  • WantedBy=multi-user.target:执行 enable 后随系统开机启动。

三、启动与开机自启

sudo systemctl daemon-reload        # 修改单元文件后必须执行
sudo systemctl enable --now demo    # 设为开机自启并立即启动
systemctl status demo               # 查看运行状态

status 输出中重点看 Active: 一行,active (running) 表示正常;如果是 failed,下面会附带最近几行日志。

四、用 journalctl 看日志

systemd 会自动收集服务的标准输出和标准错误,不用再自己重定向到文件:

journalctl -u demo -f                 # 实时跟踪日志
journalctl -u demo --since "1 hour ago"
journalctl -u demo -p err -b          # 本次开机以来的错误级别日志

如果日志占用磁盘过多,可以清理:

sudo journalctl --vacuum-size=500M

五、验证崩溃自动拉起

sudo systemctl kill -s SIGKILL demo
sleep 6 && systemctl status demo

可以看到进程 PID 变了,说明 Restart=on-failure 生效。需要注意:用 systemctl stop 正常停止的服务不会被拉起,这是符合预期的。

六、常见问题排查清单

  1. 改了配置不生效:忘记 daemon-reload,或者改的是 /lib/systemd/system 下的原始文件。推荐用 systemctl edit demo 生成覆盖片段。
  2. 提示 203/EXEC:ExecStart 路径写错或没有执行权限,必须使用绝对路径。
  3. 提示 Permission denied:User 指定的用户对工作目录或端口没有权限,1024 以下端口需要额外授权。
  4. 频繁重启后不再拉起:触发了启动频率限制,可调整 StartLimitIntervalSec 与 StartLimitBurst,再执行 systemctl reset-failed demo。
  5. 环境变量读不到:systemd 不会加载 .bashrc,要用 Environment= 或 EnvironmentFile= 显式声明。

七、进阶:给服务加上资源限制

systemd 基于 cgroup,可以直接限制服务能用的资源,防止一个服务拖垮整台机器:

[Service]
MemoryMax=512M
CPUQuota=50%
LimitNOFILE=65535

配合 systemd-cgtop 可以实时查看各服务的资源占用。

总结

相比 nohup 和手写守护脚本,systemd 提供了开机自启、崩溃重启、统一日志和资源限制一整套能力,而且几乎所有主流发行版都默认自带。把自己的程序写成一个规范的 .service 文件,是服务器运维中性价比最高的习惯之一。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。