举例:mybot.service

/etc/systemd/system/mybot.service

下面把一个标准的 /etc/systemd/system/mybot.service 文件每一行(每个关键键值对)都逐一详细解释清楚,方便你完全理解并根据自己的程序灵活修改。

[Unit]
Description=我的 Telegram/Discord 机器人
After=network.target
# Wants=postgresql.service
# Requires=mariadb.service
# Before=nginx.service

[Service]
Type=simple
User=sammy
Group=sammy
WorkingDirectory=/home/sammy/telegram-bot
Environment="PATH=/home/sammy/telegram-bot/venv/bin"
Environment=TOKEN=abcd1234yourbottoken
ExecStart=/home/sammy/telegram-bot/venv/bin/python bot.py
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=5
KillMode=process
TimeoutStopSec=30
StandardOutput=journal
StandardError=journal
# LimitNOFILE=65535
# MemoryMax=2G

[Install]
WantedBy=multi-user.target

【[Unit] 段】——描述服务本身以及依赖关系

含义 常见取值 / 举例
Description 描述 服务简要描述,systemctl status 时会显示 随便写,越清楚越好
After 后 本服务必须在哪些单元启动之后才能启动(软性依赖) After=network.target mysql.service redis.service
Before 以前 本服务必须在哪些单元启动之前启动 Before=nginx.service
Wants 想 弱依赖:启动本服务时顺便尝试启动这些单元,失败也不影响本服务 Wants=network-online.target 想要=network-online.target
Requires 需要 强依赖:这些单元没启动成功,本服务也会启动失败 Requires=docker.service
Documentation 文档 文档链接 Documentation=https://github.com/xxx/mybot 文档=https://github.com/xxx/mybot

【[Service] 段】——真正控制进程怎么跑

含义 推荐/常见取值
Type 类型 进程启动类型(极重要!选错了会启动失败或状态异常) simple(最常用)、forking、oneshot、notify、idle
• simple(默认):ExecStart 的进程就是主进程 99% 的 Python/Node/Go 程序都用这个
• forking:程序自己 fork 后父进程退出(如传统 nginx、sshd) 用这个时必须配合 PIDFile=
• oneshot:执行完就退出(如批量脚本) 配合 RemainAfterExit=yes
User / Group 用户 / 组 以哪个用户/组运行进程(强烈建议不要用 root) User=sammy Group=www-data User=sammy Group=www-data
WorkingDirectory 工作目录 进程的工作目录(相当于 cd 进这个目录再启动) /home/sammy/mybot
Environment 环境 设置环境变量(可写多行) Environment="PATH=/opt/venv/bin" Environment=“PATH=/opt/venv/bin”
ExecStart 执行启动 真正要执行的启动命令(只能有一行主命令) /usr/bin/python3 app.py /usr/bin/python3 的 app.py
ExecStartPre 启动前先执行的命令(可多行,用 + 开头表示即使失败也继续) ExecStartPre=/usr/bin/test -f /tmp/ready
ExecReload 系统 CTsystemctl reload 时执行的命令 /bin/kill -HUP $MAINPID (最常见) /bin/kill -HUP $MAINPID (最常见)
ExecStop 执行 系统 CTsystemctl stop 时执行的命令
Restart 重新启动 自动重启策略(神级选项) no、on-failure、on-abnormal、on-abort、always(最常用) 不,on-failure,on-abnormal,on-abort,总是(最常用)
RestartSec 重启安全 每次重启间隔多少秒 3、5、10
KillMode 杀戮模式 如何杀死进程 process(只杀主进程,推荐)、control-group(杀整个进程树)
TimeoutStopSec 暂停停止安全 停止服务时最多等多少秒,超时就 kill -9 30(默认 90s)
StandardOutput / StandardError 标准输出 / 标准误差 标准输出和错误输出交给哪里 journal(推荐)、syslog、file:/var/log/mybot.log journal(推荐)、syslog、file:/var/log/mybot.log

【[Install] 段】——开机自启相关

含义 常见取值
WantedBy 通缉 启用服务时(systemctl enable)会把符号链接放到哪个 target 下面 multi-user.target(无图形界面服务器) graphical.target(带桌面)
Alias 别名 给服务起个别名 Alias=mybot.service

实战小贴士(根据不同程序调整的关键点)

程序类型 Type= 类型= Restart= 重启= 其他注意事项
Python 脚本 simple 简单 always 总是 WorkingDirectory + 虚拟环境 PATH
Node.js (pm2 不用) Node.js (pm2 不用) simple 简单 always 总是
Go 编译后的二进制 simple 简单 always 总是
传统 daemon(自己 fork) forking 分 叉 always 总是 必须加 PIDFile=/run/xxx.pid
Java Jar simple 简单 always 总是 加 -Xmx -Xms,建议用 exec java -jar
只需要跑一次的脚本 oneshot 短篇 no RemainAfterExit=yes
Docker 容器 simple 简单 on-failure 失效时 ExecStart=/usr/bin/docker start mycontainer

这样你就完全掌握了 systemd service 文件每一行的意义,可以随意写出任何程序的生产级服务配置了。如果你把你要跑的具体程序(比如 frp、Ollama、qd、Aria2、WebUI、frp 内网穿透、Minecraft 服务器等)告诉我,我直接给你一份 100% 可复制粘贴的完美 .service 文件。

User / Group为什么强烈建议不要用 root?

强烈建议不要用 root 运行自己的程序(无论是 systemd 服务、tmux、nohup、docker),原因全部都是安全,一旦出事就是“全站失守”级别的事故。下面用最直白的方式给你讲清楚为什么必须用普通用户。

风险场景 用 root 运行会怎样? 用普通用户(比如 sammy)运行会怎样? 实际血案举例(真实发生过)
程序有远程代码执行漏洞(RCE) 黑客直接拿到 root shell,整台服务器彻底沦陷 最多拿到 sammy 用户权限,黑客还得再提权才能进一步搞破坏 2024 年 xz-utils 后门、2021 年 Spring4Shell、无数 Python 机器人 RCE
程序被爆破弱密码登录(SSH、Web、数据库) 黑客直接 root 权限登录 只能以普通用户登录,还需要本地提权漏洞才能进一步控制 无数被挖矿的服务器都是因为 SSH 弱密码 + root 运行的服务
程序写文件时不小心写错路径 会直接覆盖 /etc、/root、/bin 下的关键文件,导致系统损坏或留下后门 最多只能破坏自己的家目录,其他系统文件根本碰不到 有人写日志写成 > /etc/passwd,直接把自己锁死
被拖库 / 脱裤(程序里硬编码了 token) 黑客拿到 root,配合 token 可以直接控制你的云服务器、GitHub、Telegram Bot 等 普通用户就算 token 泄露,黑客也只能控制 bot,无法动服务器本身 无数 Telegram Bot token 被泄露后服务器被删库的就是 root 运行的
程序崩溃或被 kill -9 有可能留下 root 权限的残留进程或套接字,增加被利用风险 影响范围仅限当前用户
服务器被云厂商安全扫描(阿里云、腾讯云) 直接红警报“发现 root 权限服务暴露”,可能被强制下线或封号 基本没事,云厂商只关心 root 权限的服务 很多人的 frp、Ollama、WebUI 因为用 root 跑被阿里云直接停机

真实世界里踩过的大坑(2023–2025 年常见)

  1. 用 root 跑 Ollama → 被 RCE → 服务器被种矿 → 电费几万块
  2. 用 root 跑青龙面板/NoneBot → token 被爬 → 服务器被删库 + 挖矿
  3. 用 root 跑 frp 内网穿透 → 被暴力破解 → 公司内网全暴露
  4. 用 root 跑 Stable Diffusion WebUI → 被扫描到 7860 端口弱口令 → 显卡被远程挖矿
    正确的做法(几秒钟就能搞定)
# 1. 先创建一个专用普通用户(强烈推荐每个服务一个用户)
sudo adduser --disabled-password --gecos "" mybot
# 或者最低权限专用用户
sudo adduser --system --no-create-home mybot

# 2. 把代码、虚拟环境 chown 给这个用户
sudo chown -R mybot:mybot /opt/mybot

# 3. systemd 里写上
User=mybot
Group=mybot        # 或者 Group=nogroup

极简安全原则(记住这三条就永远不会被入侵)

  1. 任何自己编译/下载的程序,绝不用 root 跑
  2. 任何对外暴露端口的服务(80、443、22、frp、WebUI),必须用普通用户
  3. 实在不知道用哪个用户,就新建一个专门给这个程序用的用户
    一句话总结:
    用 root 跑服务 = 把服务器前门大开着写“欢迎来黑我”
    用普通用户跑服务 = 就算程序 0day 被打,也只是丢一个号,服务器还能保住你现在跑的任何东西(机器人、WebUI、frp、游戏服务器),如果还在用 root,赶紧改掉,真的是一键避免 99% 的血泪史。

Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

登录

注册

重设密码

请输入您的用户名或电子邮箱地址。您会收到一封包含创建新密码链接的电子邮件。