提示

返回博客列表

把下载器做成常驻服务:用 systemd 把程序跑在 Linux 后台

把下载器做成常驻服务:用 systemd 把程序跑在 Linux 后台

本地跑下载脚本,关了终端就停;放服务器上想让它 7×24 常驻、开机自启、崩溃自动拉起——这时候就该用 systemd。它是现代 Linux 发行版的标准服务管理器。这篇文章从 unit 文件结构讲起,覆盖虚拟环境、日志、资源限制、安全加固、看门狗和多实例,让你把任何命令行程序(下载器、爬虫、转码队列)封装成一个靠谱的系统服务。

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

  • nohup ... &:关终端不退出,但重启就没了、也不会自动重启;
  • screen/tmux:同理,得人盯着;
  • systemd:开机自启、挂了自动拉起、日志接 journald、资源限制一把抓、还能设看门狗。

二、准备你的程序

假设下载器在 /opt/downloader/main.py,用虚拟环境 /opt/downloader/venv。先确保它能直接跑且不依赖终端输入:

/opt/downloader/venv/bin/python /opt/downloader/main.py

确认它是长期运行、无交互的(别让它等 stdin)。

三、写 unit 文件

/etc/systemd/system/downloader.service

[Unit]
Description=VidDown Downloader Service
After=network.target
Wants=network-online.target

[Service]
Type=simple
User=downloader
Group=downloader
WorkingDirectory=/opt/downloader
ExecStart=/opt/downloader/venv/bin/python /opt/downloader/main.py
Restart=on-failure
RestartSec=5
Environment=PYTHONUNBUFFERED=1
EnvironmentFile=/opt/downloader/.env
# 资源限制
MemoryLimit=1G
CPUQuota=80%

[Install]
WantedBy=multi-user.target

要点:

  • Type=simple:主进程即 ExecStart 起的那个;若程序会 fork 后台进程用 Type=forking;支持 sd_notify 用 Type=notify
  • Restart=on-failure:非正常退出 5 秒后自动重启;always 则无论怎样都重启;
  • User/Group:别用 root 跑业务程序,建普通用户更安全;
  • PYTHONUNBUFFERED=1:日志实时进 journal,不被缓冲吞掉;
  • EnvironmentFile:从文件读环境变量(如数据库连接)。

四、启用与日常操作

sudo systemctl daemon-reload
sudo systemctl enable downloader     # 开机自启
sudo systemctl start downloader
sudo systemctl status downloader

看日志:

journalctl -u downloader -f           # 实时跟随
journalctl -u downloader --since today

五、日志轮转

journald 自带按大小/时间轮转,无需额外配置。若你想把日志也落文件:

StandardOutput=append:/var/log/downloader/out.log
StandardError=append:/var/log/downloader/err.log

再配 /etc/logrotate.d/downloader 做切割。或直接依赖 journald + journalctl --vacuum-size=500M 限制总量。

六、安全加固(生产建议)

NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/opt/downloader/data

这能大幅缩小被入侵时的破坏面。仅开放程序真正需要读写的路径。

七、看门狗(防假死)

若程序支持 systemd 看门狗协议,可设:

WatchdogSec=30
# 程序里定期调用 sd_notify("WATCHDOG=1")

超过 30 秒没"喂狗"就判定卡死并重启。不支持的话用 Restart 兜底。

八、多实例

复制 unit 改名字和端口,分别 enable:

cp downloader.service downloader-worker2.service
# 改 ExecStart 里的 --port 参数
systemctl enable downloader-worker2

九、与 Docker 的区别

维度 systemd Docker
轻量 中(有容器开销)
隔离
迁移 绑定机器 易迁移
多服务编排 强(compose/k8s)

小机器单服务用 systemd 足够;要弹性扩缩、多实例编排再上 Docker/K8s。

十、常见翻车现场

现象 根因 解法
启动失败 路径/权限错 journalctl -u downloader 看具体报错
跑一会自停 程序报错退出 查日志,修代码或放宽 Restart
不读环境变量 unit 没设 Environment=EnvironmentFile=
用了 root 有隐患 直接 root 跑 建专用用户 User=
重启不生效 没 daemon-reload 改 unit 后必跑 systemctl daemon-reload

十一、常见问题

Q:程序要收命令行参数? 直接拼在 ExecStart 后:...python main.py --port 8000

Q:怎么热更新代码? 改完代码 sudo systemctl restart downloader 即可。

Q:能限制它别吃满内存吗? 能,MemoryLimit=1G 超限会被 OOM kill 并按 Restart 重启。

Q:多实例怎么互不干扰? 复制 unit 文件、改名字/端口/工作目录,分别 enable 启动。

小结

systemd 是 Linux 后台服务的事实标准:写好 unit(注意 TypeRestartUser、环境变量),enable+start 即可常驻,日志、限资源、加固一条龙。单服务小机器首选,复杂编排再上容器。

想亲手试试?用 VidDown 一键解析下载

粘贴视频链接即可解析,多平台支持、网页端即用;下载桌面客户端解锁海外平台本地解析,开通会员更享不限次下载。

顶部