如何使用python脚本检测Discord bot是否处于离线状态
实现Discord Bot离线检测+备机自动拉起的可行方案
以下是两种落地成本低、准确率高的实现思路,可根据你的现有部署条件选择:
方案1:基于心跳上报的高可靠检测方案
该方案准确率最高,不会受Discord官方接口限制影响,适合稳定生产环境使用:
- 逻辑原理:主服务器运行的Bot每间隔30秒往共享存储内更新最新在线时间戳,备机的检测脚本定期读取该时间戳,若判定超过阈值无更新则自动拉起本地Bot进程
- 推荐用Redis做共享存储,自带过期时间能力可避免旧状态误判
主Bot端心跳上报代码(基于discord.py)
import discord from discord.ext import tasks import redis import time # 替换为你自己的Redis连接信息 r = redis.Redis(host='共享Redis服务地址', port=6379, db=0, password='Redis访问密码') bot = discord.Bot(intents=discord.Intents.all()) @tasks.loop(seconds=30) async def heartbeat_report(): # 写入时间戳同时设置5分钟过期,避免主服务挂了残留无效数据 r.set("discord_bot_last_online", time.time(), ex=300) @bot.event async def on_ready(): heartbeat_report.start() print(f"主Bot已登录: {bot.user}") bot.run("你的Discord Bot Token")
备机检测+拉起脚本
import redis import time import subprocess import os r = redis.Redis(host='共享Redis服务地址', port=6379, db=0, password='Redis访问密码') BOT_FILE_PATH = "你备机上存放的Bot启动文件路径,比如./discord_bot.py" CHECK_INTERVAL = 60 # 离线判定阈值,建议设为2分钟,避免临时网络波动导致误判 OFFLINE_THRESHOLD = 120 def is_local_bot_running(): # 检测本地是否已经启动了Bot,避免重复拉起多进程 try: return len(subprocess.check_output(["pgrep", "-f", BOT_FILE_PATH]).decode().strip()) > 0 except subprocess.CalledProcessError: return False while True: last_online = r.get("discord_bot_last_online") if not last_online or (time.time() - float(last_online)) > OFFLINE_THRESHOLD: if not is_local_bot_running(): print("主Bot判定离线,启动备机Bot") subprocess.Popen(["python3", BOT_FILE_PATH], cwd=os.path.dirname(os.path.abspath(__file__))) time.sleep(CHECK_INTERVAL)
方案2:无共享存储的简易检测方案
如果不想额外搭建共享存储,可以用Discord状态查询能力实现检测,适合个人小型Bot使用:
- 逻辑原理:申请一个专门用来做检测的测试Bot,和你要托管的业务Bot加入同一个私有服务器,测试Bot定期查询业务Bot的在线状态,判定离线后直接拉起本地进程
- 注意需要在Discord开发者后台给测试Bot开启
Presence Intent和Server Members Intent权限
备机检测脚本示例
import discord from discord.ext import tasks import subprocess import os CHECK_BOT_TOKEN = "检测用测试Bot的Token" TARGET_BOT_ID = 123456789 # 替换为你业务Bot的数字用户ID GUILD_ID = 987654321 # 替换为两个Bot共同加入的服务器数字ID BOT_FILE_PATH = "备机上的业务Bot启动文件路径" intents = discord.Intents.default() intents.presences = True intents.members = True check_bot = discord.Bot(intents=intents) def is_local_bot_running(): try: return len(subprocess.check_output(["pgrep", "-f", BOT_FILE_PATH]).decode().strip()) > 0 except subprocess.CalledProcessError: return False @tasks.loop(minutes=1) async def check_bot_status(): guild = check_bot.get_guild(GUILD_ID) target_member = guild.get_member(TARGET_BOT_ID) if target_member.status == discord.Status.offline: if not is_local_bot_running(): print("主Bot判定离线,启动备机Bot") subprocess.Popen(["python3", BOT_FILE_PATH], cwd=os.path.dirname(os.path.abspath(__file__))) @check_bot.event async def on_ready(): check_bot_status.start() check_bot.run(CHECK_BOT_TOKEN)
注意事项
- 所有方案都必须加本地进程重复启动校验,避免网络波动、接口延迟等情况导致重复拉起多个Bot进程,触发官方限流
- 可按需扩展告警逻辑,检测到离线时触发Discord私信、邮件等通知,方便你及时排查主服务器故障
- 担心共享存储单点故障的话,可以同时运行两套检测逻辑做双重校验,降低误判概率
- 如果业务Bot用了分片、集群部署,需要把所有分片的心跳状态都做上报,避免单分片离线没检测到
内容的提问来源于stack exchange,提问作者JonaPoka
相关产品推荐
相关产品推荐

