RDP Monster

Discord 机器人 VPS 托管:7×24 小时保持在线

Discord 机器人 VPS 托管:7×24 小时保持在线

为什么 VPS 才能让 Discord 机器人真正常在线

Discord 机器人不是网页。登录之后,它会与 Discord 的 gateway 保持一条长连接 WebSocket,并持续响应心跳;进程一旦停止,机器人立即显示离线,所有命令失效。仅“进程永不休眠”这一条要求,就排除了大多数“免费”托管:

  • Heroku 已于 2022 年 11 月取消免费 dyno。
  • Replit 不再让免费项目常驻运行,常在线功能已转为付费部署。
  • Glitch 已于 2025 年终止应用托管服务。
  • 闲置后休眠的免费 Web 方案每次空闲都会切断 gateway 连接;在用户看来,机器人就是挂了。

把 Discord 机器人托管在 VPS 上能从根本上解决问题:一台全天候运行、拥有 root 权限的 Linux 机器,机器人只是由 init 系统管理的一个普通服务。本指南在 Ubuntu 24.04(同样适用于 22.04 和 Debian 12)上,用 discord.py 与 discord.js 完成搭建,并涵盖 token 管理、自动重启、日志、更新和内存规划。

准备 VPS:专用账号与运行环境

先守好大门:在 Ubuntu 上启用并加固 SSH,使用密钥认证、禁止 root 登录并启用 ufw。机器人是主动外连 Discord 的,不需要任何入站端口,因此防火墙除 SSH 外可以全部关闭。

第 1 步:为机器人创建一个非特权账号

sudo useradd -r -m -d /opt/mybot -s /usr/sbin/nologin bot

使用独立账号后,有缺陷的机器人或被投毒的 npm、PyPI 依赖都无法读取你的 SSH 密钥或影响其他服务。所有文件都放在 /opt/mybot,属主为 bot。

第 2 步(Python):在虚拟环境中安装 discord.py

sudo apt update && sudo apt install -y python3 python3-venv python3-pip
sudo -u bot python3 -m venv /opt/mybot/.venv
sudo -u bot /opt/mybot/.venv/bin/pip install -U discord.py python-dotenv

discord.py 2.x 需要 Python 3.8 或更高版本;Ubuntu 24.04 自带 3.12,22.04 自带 3.10,直接用系统解释器即可。只有需要语音频道时才安装 discord.py[voice] 和 ffmpeg。

第 3 步(Node.js):安装当前 LTS 版本与 discord.js

curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
sudo -u bot bash -c 'cd /opt/mybot && npm init -y && npm install discord.js dotenv'

Ubuntu 自带的 nodejs 包版本远落后于上游,而 discord.js v14 需要较新的运行时,因此请用上面的 NodeSource 或 nvm 安装当前 LTS。若使用 nvm,请执行 which node,并在服务单元里填写该绝对路径。

别把 token 写进代码:使用 .env 文件

机器人 token 相当于可完全操控机器人的密码:绝不要粘贴进 bot.py 或 index.js,更不要提交到仓库。把它写进 /opt/mybot/.env,仅机器人账号可读,并用编辑器而不是 echo 编写,因为命令行里输入的 token 会留在 shell 历史记录中:

sudo -u bot nano /opt/mybot/.env        # one line: DISCORD_TOKEN=your-token-here
sudo chmod 600 /opt/mybot/.env
echo ".env" | sudo -u bot tee -a /opt/mybot/.gitignore

格式为每行一个 KEY=value,不要加引号,也不要写 export。python-dotenv 和 npm 包 dotenv 都能读取它,systemd 也可以用 EnvironmentFile= 注入同一个文件(见下一节);两者同时使用没有问题,因为这两个库都不会覆盖已存在的变量。一旦 token 泄露,请立即在 Developer Portal 的 Bot → Reset Token 中重置。

discord.py 与 discord.js 的最小示例

两个示例都从环境变量读取 token,启用 Message Content intent,并响应 !ping。在 Developer Portal 中创建应用、添加 bot 用户、复制 token(只显示一次),在 Bot → Privileged Gateway Intents 下启用 Message Content Intent,然后通过 OAuth2 URL generator 用 bot scope 把机器人邀请到测试服务器。

discord.py: /opt/mybot/bot.py

import os
import discord
from dotenv import load_dotenv

load_dotenv()

intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)

@client.event
async def on_ready():
    print(f"Logged in as {client.user}")

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    if message.content == "!ping":
        await message.channel.send("pong")

client.run(os.environ["DISCORD_TOKEN"])

discord.js: /opt/mybot/index.js

require("dotenv").config();
const { Client, GatewayIntentBits, Events } = require("discord.js");

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent,
  ],
});

client.once(Events.ClientReady, (c) => {
  console.log(`Logged in as ${c.user.tag}`);
});

client.on(Events.MessageCreate, (message) => {
  if (message.author.bot) return;
  if (message.content === "!ping") message.reply("pong");
});

client.login(process.env.DISCORD_TOKEN);

先在前台运行一次:sudo -u bot /opt/mybot/.venv/bin/python /opt/mybot/bot.py 或 sudo -u bot node /opt/mybot/index.js,等待出现 Logged in as,发送 !ping,然后按 Ctrl-C。此时机器人的生命周期仅限于当前 SSH 会话:关闭终端会向子进程发送 SIGHUP,机器人随即退出。

用 systemd 加 Restart=always 常驻运行

systemd 本就是 Ubuntu 的 init 系统,因此让机器人在退出登录、崩溃和重启后继续在线,最干净的方式就是写一个 service 单元:不需要额外守护进程,日志也直接进入 journal。

第 1 步:编写单元文件

sudo nano /etc/systemd/system/mybot.service
[Unit]
Description=Discord bot
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=bot
Group=bot
WorkingDirectory=/opt/mybot
EnvironmentFile=/opt/mybot/.env
Environment=PYTHONUNBUFFERED=1
ExecStart=/opt/mybot/.venv/bin/python /opt/mybot/bot.py
Restart=always
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/mybot

[Install]
WantedBy=multi-user.target

使用 discord.js 时,请设置 ExecStart=/usr/bin/node /opt/mybot/index.js 并删除 PYTHONUNBUFFERED 那一行。关键指令如下:

  • Restart=always 会在进程以任何方式退出时重启它,无论是崩溃还是正常的 sys.exit();RestartSec=5 可防止秒退的机器人(token 错误、语法错误)陷入高频重启循环。
  • Wants=/After=network-online.target 会等网络就绪后再启动,避免重启后首次登录因 DNS 失败。
  • PYTHONUNBUFFERED=1:没有终端时 Python 会对 stdout 做块缓冲,print() 的内容要么延迟数分钟,要么直到退出才进入 journal。
  • Protect*、PrivateTmp 和 NoNewPrivileges 这几行让文件系统的其余部分对机器人只读或不可见;机器人需要写入的目录请加入 ReadWritePaths=。

第 2 步:启用、启动并验证

sudo systemctl daemon-reload
sudo systemctl enable --now mybot
systemctl status mybot
sudo systemctl kill --signal=KILL mybot   # simulate a crash; status is active again after 5 s

enable 会创建开机自启的符号链接,--now 则立即启动单元。kill 那一行才是真正的测试:若几秒后 systemctl status mybot 显示 active (running),说明重启策略生效;再执行 sudo reboot 即可验证开机自启。想和其他服务一起查看,可以用 systemctl 列出正在运行的服务;它会显示为 mybot.service,而 systemctl is-enabled mybot 可确认它会在重启后自动恢复。

替代方案:pm2,以及它与 screen、nohup、Docker 的对比

所有让机器人常驻的方式,都要回答三个问题:SSH 退出后能否存活?崩溃后能否重启?开机后能否自启?

方式SSH 退出后存活崩溃后重启开机自启结论
nohup / &是否否仅适合快速测试。
screen / tmux是否否,除非自行编写脚本用于调试,不适合生产。
pm2是是是,需先执行 pm2 startup + pm2 save适合 Node.js 团队;一个命令行工具搞定日志与重启。
systemd 单元是是(Restart=)是(enable)推荐;无需额外软件,内置安全加固。
Docker,restart: unless-stopped是是是,依赖 Docker 守护进程当机器人本来就以镜像分发时很合适。

pm2 在 Node.js 生态中很流行,也能管理 Python 进程。请以拥有机器人的那个账号运行它:

sudo npm install -g pm2
cd /opt/mybot
pm2 start index.js --name mybot
pm2 start bot.py --name mybot --interpreter /opt/mybot/.venv/bin/python   # Python variant
pm2 save
pm2 startup                    # prints a sudo command to run once
pm2 logs mybot
pm2 install pm2-logrotate      # ~/.pm2/logs/ otherwise grows forever

pm2 startup 会生成一个 pm2-<user> 的 systemd 单元,在开机时恢复你保存的进程列表,也就是说 pm2 是叠在 systemd 之上而非取代它,这正是单个机器人直接用 systemd 的理由。当你有多个 Node 进程,或团队已经熟悉 pm2 时,它才真正物有所值。

如果你偏好容器,对应做法是在 Compose 文件里写 restart: unless-stopped;在 Ubuntu VPS 上安装 Docker 的教程涵盖了引擎、Compose 与开机行为。其中关于 ufw 的注意事项不影响机器人,因为它不对外暴露端口。

日志、更新与内存规划

日志

journalctl -u mybot -f                    # follow live
journalctl -u mybot --since "1 hour ago"
journalctl -u mybot -p err -b             # errors since boot
sudo journalctl --vacuum-size=200M        # cap journal size

journald 会自动轮转并压缩日志。如果机器人自己写日志文件,请在 Python 中使用 logging.handlers.RotatingFileHandler,或在 Node 中为 pino、winston 配置轮转传输,避免话痨式日志把磁盘写满。

更新

cd /opt/mybot
sudo -u bot git pull
sudo -u bot .venv/bin/pip install -U -r requirements.txt   # Node: sudo -u bot npm ci
sudo systemctl restart mybot

重启会让 gateway 连接中断几秒;库会自动重连,用户几乎察觉不到。请在 requirements.txt 或 package-lock.json 中锁定库版本,大版本升级前先读变更日志。用 sudo apt update && sudo apt upgrade 或 unattended-upgrades 保持系统更新。

机器人需要多少内存?

不要按通用数字估算,要实测。systemctl status mybot 会输出一行 Memory:,pm2 list 也能看到同样的数据。纯命令型的 discord.py 机器人空闲时通常只占几十 MB;discord.js 机器人还要加上 Node 运行时的开销。内存占用随状态增长:大型服务器的成员与消息缓存、语音与音乐(每条流一个 ffmpeg 进程)、图像生成或数据库。实际经验是,1 GB 内存足以从容运行系统加一个中小型机器人;语音密集型机器人或同机多个机器人则需要 2 GB 以上;超过 2,500 个服务器时 Discord 要求分片,占用会成倍增加。两个低成本的安全网:在单元里写 MemoryMax=512M,让内存泄漏只导致机器人重启而不是拖垮整机;再加一个小的 swap 文件。

以上一切的前提,是一台全天候在线、拥有 root 权限的 Linux 机器。如果你还差这台机器,rdp.monster 的 Discord 机器人 VPS 在付款确认后约 10 秒即可上线,提供独享 CPU 与内存、完整 root 权限、不限量(公平使用)带宽、无需 KYC、支持加密货币付款,每月 $8.99 起,让上面的 systemctl enable --now mybot 成为机器人变绿之前你敲下的最后一条命令。

常见问题

可以免费 7×24 小时托管 Discord 机器人吗?

已经不再可靠:那些能让机器人保持唤醒的免费方案要么被取消,要么现在闲置就休眠。
Heroku 于 2022 年 11 月取消免费 dyno,Replit 把常在线转为付费部署,Glitch 于 2025 年终止应用托管。剩下的免费 Web 方案闲置后会休眠,从而切断机器人的 gateway 连接。放在自己电脑上跑也行,直到电脑重启或睡眠为止。最便宜又可靠的选择,是一台约 1 GB 内存的小型 VPS:systemd 会在崩溃和重启后拉起机器人,也没人会因为它空闲而挂起它。

Discord 机器人需要固定 IP 或在 VPS 上开放端口吗?

不需要:机器人是主动外连 Discord 的,无需开放任何入站端口,IP 也无关紧要。
gateway 类机器人向 Discord 发起一条出站 WebSocket,并通过同一条连接接收事件,因此 VPS 防火墙除 SSH 外可以全部关闭,服务器 IP 也不会暴露给用户。只有当你改用 HTTP interaction endpoints(Discord 会调用你注册的 URL),或增加 Web 控制面板时,才需要开放端口和公网域名。这种情况下请用反向代理把它放在 HTTPS 之后。

可以在同一台 VPS 上运行多个 Discord 机器人吗?

可以,每个机器人一个 systemd 单元(或 pm2 进程),最好各自使用独立用户和目录。
并没有一机一机器人的限制。为每个机器人分配独立目录,例如 /opt/bot-a 和 /opt/bot-b,各自的 .env 与 token,以及各自的单元文件,然后分别执行 systemctl enable --now。使用不同的系统用户,可避免一个机器人的漏洞读到另一个的 token。唯一共享的预算是内存和 CPU:逐个单元查看 systemctl status,总量接近上限时就升级到更大的套餐。

Discord 机器人该托管在 Windows 还是 Linux VPS 上?

机器人默认选 Linux:更便宜、更轻量,而且相关工具(systemd、pm2、Docker)本就为它而生。
discord.py 和 discord.js 都能在 Windows 上运行;如果机器人依赖仅限 Windows 的程序,或你就是更习惯图形桌面,那么 Windows VPS 是对的选择。但对普通机器人来说,Linux 更优:系统本身只占很少内存,最小化安装几乎没有攻击面,让进程常驻也只需十行的 systemd 单元。在 Windows 上,你得用 Task Scheduler 或 NSSM 才能实现同样的开机自启,操作还更繁琐。

Adrien Roche, 基础设施与主机托管编辑

系统工程师,拥有 10 年以上运维 Windows Server 和 Linux 集群的经验。Adrien 负责 rdp.monster 的基础设施文档,并撰写关于 RDP、VPS 托管、服务器管理、网络和隐私工具的指南。

注册加入我们的分销商计划

您的信息

如有任何疑问, 点击这里联系我们 !
姓名(必填)
请填写您的邮箱地址,您必须拥有以下网站的账号: manager.rdp.monster !

您的公司

如果您有网站,请填写网址
请简要说明您打算如何向客户销售服务,例如在论坛上与人交流推广。

连怪兽都爱吃 cookie!

我们使用 cookie 来改善您的浏览体验、提供个性化的广告或内容,并分析网站流量。点击「接受」即表示您同意我们使用 cookie。