Discord 积极打击自动化和机器人,使用先进的检测系统:分析 IP 地址、行为模式和速率限制。如果您在服务器上运行用于管理、发送消息或自动化操作的机器人,而没有正确设置的代理,您将在工作开始的头几个小时内就会遇到封禁。在本指南中,我们将讨论哪些代理适合 Discord,如何设置 IP 轮换以及如何绕过平台的保护机制。
为什么 Discord 封禁机器人以及保护机制如何工作
Discord 使用多层保护系统来防止自动化,同时分析多个参数。该平台不仅检查来自单个 IP 的请求数量——它还构建每个连接的行为档案,并将其与正常用户的模式进行比较。
Discord 中检测机器人的主要机制:
- 速率限制 — Discord 对单位时间内的操作数量设置严格限制。例如,来自一个账户的 5 条消息不得超过 5 秒,API 每分钟不得超过 50 次请求。超过限制会导致临时封禁(HTTP 429)。
- IP 地址分析 — 如果多个机器人从同一 IP 工作或观察到可疑活动(快速切换账户、大规模操作),Discord 可能会封禁整个 IP 地址数小时或数天。
- 连接指纹识别 — 平台分析技术参数:User-Agent、请求头、库版本、响应时间。如果参数与普通 Discord 客户端不符,账户会被标记为可疑。
- 行为分析 — Discord 跟踪操作模式:反应过快、消息之间的间隔完美、操作缺乏随机性。按照严格算法工作的机器人更容易被发现。
没有代理的典型封禁场景:
- 从一个家庭 IP 启动 3-5 个机器人 — 在工作开始后 2-6 小时内封禁 IP
- 大规模发送服务器邀请 — 在发送 10-15 个邀请后封禁账户和 IP
- 自动化管理(删除消息、分配角色) — 当来自一个 IP 的操作超过 100 次/小时时封禁
- 解析服务器成员 — 在扫描 200-300 个个人资料后被发现并封禁
代理可以解决这些问题,通过在不同的 IP 地址之间分配请求,创建来自不同位置的普通用户的假象。但重要的是要正确选择代理类型并设置轮换——不正确的配置可能导致更快的封禁。
哪些类型的代理适合 Discord 机器人
代理类型的选择取决于您的任务:机器人的数量、请求的频率、预算和所需的匿名级别。我们将讨论三种主要类型的代理及其在 Discord 中的应用。
| 代理类型 | 优点 | 缺点 | 适合于 |
|---|---|---|---|
| 数据中心代理 | 高速度(延迟 10-50 毫秒)、低价格(每月 $1-3)、稳定性 | Discord 容易识别数据中心的 IP,进行大规模操作时封禁风险高 | 测试、轻度自动化(1-2 个机器人)、没有大规模请求的任务 |
| 住宅代理 | 真实家庭用户的 IP,最低封禁风险,大量地址池(数百万个 IP) | 中等速度(延迟 100-300 毫秒),价格较高(每 GB 流量 $5-15),某些 IP 不稳定 | 大规模发送、服务器解析、与 5 个以上的机器人一起工作、长期项目 |
| 移动代理 | 移动运营商的 IP(4G/5G),Discord 的最大信任,动态 IP 切换 | 高价格(每月 $50-150),地址池较小,可能会出现连接中断 | 关键账户、绕过严格封禁、处理高价值账户 |
不同任务的选择建议:
管理和服务器管理(1-3 个机器人): 固定 IP 的住宅代理。一个机器人 — 一个 IP,不进行轮换。这会创建一个稳定的连接档案,Discord 会将其视为普通的管理员用户。
大规模发送和邀请(10 个以上的机器人): 每 5-10 分钟轮换的住宅代理。分配负载:每个 IP 每小时不超过 20 次操作。为 10 个机器人使用 50 个以上的 IP 地址池。
解析成员和服务器: 快速轮换的住宅代理(每 1-3 分钟)或移动代理。解析是最冒险的活动之一,Discord 容易计算扫描模式。在请求之间使用随机延迟(30-120 秒)。
测试和开发: 数据中心代理足以调试功能。但在生产环境中运行之前,务必切换到住宅代理——Discord 的行为可能因不同类型的 IP 而异。
重要事项:Discord 对来自某些国家和地区的 IP 地址特别严格。来自俄罗斯、中国、越南、印度的 IP 会因垃圾邮件活动的高频率而受到更严格的检查。如果您的目标受众在美国或欧洲,请使用这些地区的代理——这将降低 40-60% 的封禁概率。
如何通过代理绕过 Discord 的速率限制
Discord 的速率限制是对单位时间内 API 请求数量的限制。它们有两种类型:全局(针对整个应用)和每路由(针对特定端点)。代理有助于在不同的 IP 之间分配负载,但这并不意味着可以忽略限制——Discord 在机器人令牌级别跟踪活动。
Discord API 的主要速率限制:
- 发送消息:每个频道每 5 秒 5 条消息,机器人全局每 10 秒 50 条消息
- 创建/删除频道:每 10 分钟 50 次请求
- 更改成员角色:每 10 秒 10 次请求
- 获取成员列表:每秒 1 次请求(最严格的限制)
- 发送 DM(私人消息):每 5 秒 5 次 DM,向不认识的用户进行大规模发送会被封禁
当您超过限制时,Discord 会返回 HTTP 429(请求过多),并带有 Retry-After 头,指示等待时间(以秒为单位)。正确处理此响应至关重要。
通过代理绕过速率限制的策略:
# Python 示例 (discord.py) 在速率限制时轮换代理
import discord
from discord.ext import commands
import aiohttp
import asyncio
import random
class ProxyRotator:
def __init__(self, proxy_list):
self.proxies = proxy_list # ['http://user:pass@ip:port', ...]
self.current_index = 0
self.failed_proxies = set()
def get_next_proxy(self):
# 跳过不可用的代理
available = [p for p in self.proxies if p not in self.failed_proxies]
if not available:
self.failed_proxies.clear() # 完整循环后重置
available = self.proxies
proxy = available[self.current_index % len(available)]
self.current_index += 1
return proxy
def mark_failed(self, proxy):
self.failed_proxies.add(proxy)
# 初始化
proxy_rotator = ProxyRotator([
'http://user1:pass1@192.168.1.1:8080',
'http://user2:pass2@192.168.1.2:8080',
# ... 添加 10-20 个代理以确保稳定运行
])
intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents)
async def send_with_retry(channel, message, max_retries=3):
"""发送消息并自动处理速率限制"""
for attempt in range(max_retries):
try:
# 每次尝试获取新代理
proxy = proxy_rotator.get_next_proxy()
# Discord.py 在内部使用 aiohttp,设置代理
connector = aiohttp.TCPConnector()
async with aiohttp.ClientSession(connector=connector) as session:
bot.http.connector = connector
bot.http.proxy = proxy
await channel.send(message)
return True
except discord.HTTPException as e:
if e.status == 429: # 速率限制
retry_after = e.retry_after if hasattr(e, 'retry_after') else 5
print(f"速率限制!等待 {retry_after} 秒,切换代理...")
# 将代理标记为暂时不可用
proxy_rotator.mark_failed(proxy)
# 为延迟添加随机性
await asyncio.sleep(retry_after + random.uniform(1, 3))
else:
print(f"发送错误:{e}")
await asyncio.sleep(2)
return False
@bot.event
async def on_ready():
print(f'机器人已启动:{bot.user}')
# 示例用法
@bot.command()
async def mass_send(ctx):
channels = ctx.guild.text_channels[:5] # 前 5 个频道
for channel in channels:
success = await send_with_retry(channel, "测试消息")
if success:
print(f"已发送到 {channel.name}")
# 频道之间的随机延迟
await asyncio.sleep(random.uniform(3, 7))
绕过速率限制的关键原则:
- 始终处理 HTTP 429:不要忽略 Retry-After 头。Discord 在重复违规时会增加封禁时间(从 5 秒到 60 秒及以上)。
- 添加随机性:请求之间的延迟应为随机(例如,2-5 秒而不是固定的 3 秒)。这模拟了人类的行为。
- 分配负载:如果您有 10 个机器人和 20 个代理,请为每个机器人分配 2 个代理进行轮换。不要为所有机器人使用一个代理。
- 监控代理质量:某些 IP 可能已经被 Discord 封禁。自动排除那些持续返回 403 或 429 的代理。
不同任务的 IP 轮换策略
代理的轮换不仅仅是每 N 分钟随机更换 IP。正确的策略取决于机器人的活动类型和 Discord 对连接稳定性的要求。我们将讨论四种主要方法。
1. 固定 IP(无轮换)
何时使用:管理机器人、服务器管理机器人、音乐机器人、在服务器上持续存在的机器人。
逻辑:一个机器人 = 整个工作期间的一个 IP(数周、数月)。Discord 将这样的连接视为普通的管理员用户,总是从同一个地方登录。
设置:
# Python (discord.py) - 固定代理
import discord
from discord.ext import commands
PROXY = 'http://username:password@192.168.1.100:8080'
intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents, proxy=PROXY)
# 该代理将用于该机器人的所有请求
bot.run('YOUR_BOT_TOKEN')
优点:最大稳定性,最低的 IP 封禁风险,简单的设置。
缺点:如果 IP 被封禁,必须手动更换代理并重新创建机器人的会话。
2. 按时间轮换
何时使用:发送机器人、活动适中的机器人(每小时 10-50 次操作)、低频率的数据解析。
逻辑:每 5-15 分钟根据计时器更换 IP,无论请求数量如何。这模拟了一个用户重新连接到互联网(例如,动态 IP 的移动互联网)。
推荐间隔:
- 低活动(5-10 次操作/小时):每 10-15 分钟轮换一次
- 中等活动(20-40 次操作/小时):每 5-7 分钟轮换一次
- 高活动(50 次以上操作/小时):每 2-3 分钟轮换一次 + 在速率限制时额外轮换
# JavaScript (discord.js) - 按时间轮换
const { Client, GatewayIntentBits } = require('discord.js');
const HttpsProxyAgent = require('https-proxy-agent');
const proxies = [
'http://user1:pass1@ip1:port',
'http://user2:pass2@ip2:port',
'http://user3:pass3@ip3:port',
];
let currentProxyIndex = 0;
function getProxyAgent() {
const proxy = proxies[currentProxyIndex];
currentProxyIndex = (currentProxyIndex + 1) % proxies.length;
return new HttpsProxyAgent(proxy);
}
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
rest: { agent: getProxyAgent() }
});
// 每 5 分钟轮换
setInterval(() => {
console.log('切换代理...');
client.rest.setAgent(getProxyAgent());
}, 5 * 60 * 1000);
client.login('YOUR_BOT_TOKEN');
3. 按请求数量轮换
何时使用:大规模解析、服务器成员抓取、自动邀请。
逻辑:在执行 N 次请求后更换 IP(例如,每 20-50 次请求)。这可以均匀分配负载,并避免超过 Discord 对单个 IP 的隐性限制。
推荐的 N 值:
- 解析成员:每个 IP 30-50 次请求(以避免被发现扫描模式)
- 发送 DM:每个 IP 10-15 条消息(Discord 对大规模 DM 特别严格)
- 创建邀请:每个 IP 20-30 个邀请
4. 自适应轮换(在错误时)
何时使用:关键机器人、高价值账户的操作、绕过严格封禁。
逻辑:在收到 429(速率限制)、403(禁止)或超时错误时自动更换 IP。系统会记住“坏” IP,并暂时将其排除在轮换之外。
# Python - 自适应轮换与黑名单
import time
from collections import defaultdict
class AdaptiveProxyRotator:
def __init__(self, proxies):
self.proxies = proxies
self.current = 0
self.error_count = defaultdict(int)
self.blacklist_until = {} # {proxy: timestamp}
def get_proxy(self):
now = time.time()
# 过滤黑名单中的代理
available = [
p for p in self.proxies
if p not in self.blacklist_until or self.blacklist_until[p] < now
]
if not available:
# 如果所有代理都在黑名单中,重置并等待
print("所有代理都在黑名单中,等待 60 秒...")
time.sleep(60)
self.blacklist_until.clear()
available = self.proxies
proxy = available[self.current % len(available)]
self.current += 1
return proxy
def report_error(self, proxy, error_type):
self.error_count[proxy] += 1
# 多次错误时临时封禁
if self.error_count[proxy] >= 3:
blacklist_duration = 300 # 5 分钟
self.blacklist_until[proxy] = time.time() + blacklist_duration
print(f"代理 {proxy} 在黑名单中 {blacklist_duration} 秒")
self.error_count[proxy] = 0 # 重置计数器
def report_success(self, proxy):
# 成功请求 - 重置错误计数器
if proxy in self.error_count:
self.error_count[proxy] = max(0, self.error_count[proxy] - 1)
组合方法(推荐): 使用基本的按时间轮换(每 5-10 分钟) + 在错误时的自适应轮换。这确保了稳定性并能快速响应问题。
在流行库中设置代理:discord.py 和 discord.js
我们将逐步讨论如何在两个最流行的 Discord 机器人库中设置代理。这些示例适用于大多数任务,并且易于根据您的需求进行调整。
Discord.py(Python)
Discord.py 使用 aiohttp 进行 HTTP 请求。代理通过在创建客户端时使用 proxy 参数进行设置,或者通过直接设置 HTTP 会话。
步骤 1:安装依赖
pip install discord.py aiohttp aiohttp-socks
# aiohttp-socks 是用于 SOCKS5 代理的,对于 HTTP/HTTPS 并不是必需的
步骤 2:使用单个代理的基本设置
import discord
from discord.ext import commands
# 代理格式:protocol://username:password@ip:port
PROXY = 'http://user:pass@192.168.1.100:8080'
intents = discord.Intents.default()
intents.message_content = True # 用于读取消息
bot = commands.Bot(
command_prefix='!',
intents=intents,
proxy=PROXY # 所有 HTTP 请求的代理
)
@bot.event
async def on_ready():
print(f'机器人 {bot.user} 通过代理连接!')
@bot.command()
async def ping(ctx):
await ctx.send(f'pong!延迟:{round(bot.latency * 1000)}ms')
bot.run('YOUR_BOT_TOKEN')
步骤 3:使用代理轮换的设置
import discord
from discord.ext import commands, tasks
import aiohttp
import random
PROXIES = [
'http://user1:pass1@ip1:port',
'http://user2:pass2@ip2:port',
'http://user3:pass3@ip3:port',
]
class ProxyBot(commands.Bot):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.current_proxy = random.choice(PROXIES)
self.proxy_rotation.start()
@tasks.loop(minutes=5) # 每 5 分钟轮换
async def proxy_rotation(self):
old_proxy = self.current_proxy
self.current_proxy = random.choice([p for p in PROXIES if p != old_proxy])
# 使用新代理重新创建 HTTP 会话
await self.http.close()
connector = aiohttp.TCPConnector(limit=0)
self.http.connector = connector
self.http.__session = aiohttp.ClientSession(connector=connector)
print(f'代理已更改:{old_proxy} -> {self.current_proxy}')
async def close(self):
self.proxy_rotation.cancel()
await super().close()
intents = discord.Intents.default()
bot = ProxyBot(command_prefix='!', intents=intents)
bot.run('YOUR_BOT_TOKEN')
Discord.js(Node.js)
Discord.js 没有内置的代理支持,因此使用 https-proxy-agent 或 socks-proxy-agent 库。
步骤 1:安装依赖
npm install discord.js https-proxy-agent
# 对于 SOCKS5:npm install socks-proxy-agent
步骤 2:基本设置
const { Client, GatewayIntentBits } = require('discord.js');
const { HttpsProxyAgent } = require('https-proxy-agent');
const PROXY = 'http://user:pass@192.168.1.100:8080';
const agent = new HttpsProxyAgent(PROXY);
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
],
rest: { agent: agent } // REST API 请求的代理
});
client.on('ready', () => {
console.log(`机器人 ${client.user.tag} 通过代理连接!`);
});
client.on('messageCreate', async (message) => {
if (message.content === '!ping') {
await message.reply(`pong!WebSocket 延迟:${client.ws.ping}ms`);
}
});
client.login('YOUR_BOT_TOKEN');
步骤 3:代理轮换
const { Client, GatewayIntentBits } = require('discord.js');
const { HttpsProxyAgent } = require('https-proxy-agent');
const PROXIES = [
'http://user1:pass1@ip1:port',
'http://user2:pass2@ip2:port',
'http://user3:pass3@ip3:port',
];
let currentProxyIndex = 0;
function getNextProxy() {
const proxy = PROXIES[currentProxyIndex];
currentProxyIndex = (currentProxyIndex + 1) % PROXIES.length;
return new HttpsProxyAgent(proxy);
}
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
rest: { agent: getNextProxy() }
});
// 每 10 分钟轮换
setInterval(() => {
const newAgent = getNextProxy();
client.rest.setAgent(newAgent);
console.log('代理已更改');
}, 10 * 60 * 1000);
client.on('ready', () => {
console.log(`机器人 ${client.user.tag} 启动`);
});
client.login('YOUR_BOT_TOKEN');
重要: WebSocket 连接(用于实时事件接收)并不总是支持代理。如果您在通过 WebSocket 连接时遇到问题,请仅对 REST API 请求使用 HTTP 代理,而将 WebSocket 保持无代理。对于关键情况,请考虑使用 VPN 而不是代理进行 WebSocket 连接。
常见错误及如何避免
即使使用正确设置的代理,也可能因常见错误而被封禁。我们将讨论其中最关键的错误及其解决方法。
错误 1:为所有机器人使用一个代理
问题:您通过一个 IP 地址启动 5-10 个机器人。Discord 看到多个账户从同一个 IP 同时活动,封禁所有账户和该 IP。
解决方案:稳定运行的规则是“一个机器人 — 一个唯一的 IP”。如果您有 10 个机器人,至少使用 10 个不同的代理。对于关键项目,增加 50-100% 的备用(10 个机器人使用 15-20 个代理)以进行轮换。
错误 2:IP 轮换过快
问题:您每 30-60 秒更换一次 IP,认为这可以防止封禁。实际上,Discord 将频繁更换 IP 视为可疑活动——普通用户不会每分钟重新连接一次互联网。
解决方案:最小轮换间隔为 3-5 分钟。最佳选择是根据请求强度设定为 5-15 分钟。例外情况是当收到速率限制(429)时的自适应轮换。
错误 3:忽视代理的地理位置
问题:您的机器人“居住”在美国的服务器上,但使用来自俄罗斯、中国或印度的代理。Discord 看到服务器的声明位置与 IP 地址不符,这增加了可疑性。
解决方案:使用与您的 Discord 服务器或目标受众位于同一国家/地区的代理。对于国际项目,选择来自美国或欧洲的代理——它们在 Discord 中的声誉更好。
错误 4:缺乏错误处理
问题:机器人收到 HTTP 429(速率限制)后继续发送请求,导致情况恶化。Discord 会随着每次尝试增加封禁时间。
解决方案:始终处理错误代码:
- 429(请求过多):读取 Retry-After 头并等待指定时间 + 1-3 秒。切换代理。
- 403(禁止):IP 或令牌被封禁。切换代理,检查令牌的有效性。
- 401(未授权):无效的机器人令牌。检查 Discord 开发者门户中的令牌。
- 502/504(网关错误):代理或 Discord API 出现问题。等待 10-30 秒,切换代理。
错误 5:使用公共或廉价代理
问题:免费的或廉价的代理(每个 IP $0.5-1)通常已经被 Discord 封禁,因为成千上万的其他机器人和垃圾邮件发送者使用过它们。
解决方案:投资于可靠提供商的优质住宅代理。在使用之前检查 IP 的声誉(使用 AbuseIPDB、IPQualityScore 等服务)。一个价值 $5-10 的优质代理比 10 个被封禁的代理更好。
错误 6:所有机器人的 User-Agent 相同
问题:所有机器人都使用库的标准 User-Agent(例如,“DiscordBot(discord.py 2.0)”)。Discord 容易将这些连接分组并检测到大规模自动化。
解决方案:在机器人之间变更 User-Agent。使用现实的值:
# Python - 自定义 User-Agent
import discord
class CustomBot(discord.Client):
async def request(self, *args, **kwargs):
# 重写 User-Agent
if 'headers' not in kwargs:
kwargs['headers'] = {}
kwargs['headers']['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Discord/1.0.9015'
return await super().request(*args, **kwargs)
监控机器人的工作和处理错误
正确的监控可以在问题导致大规模封禁之前发现它们。我们将讨论通过代理监控 Discord 机器人的关键指标和工具。
监控指标
| 指标 | 监控内容 | 关键值 |
|---|---|---|
| 429 错误频率 | 每小时的速率限制错误数量 | >10 次/小时 — 请重新审视请求策略 |
| 403 错误频率 | IP 或令牌的封禁情况 | >3 次/天 — 代理被泄露 |
| 延迟(latency) | 代理 + Discord API 的响应时间 | >1000ms — 代理缓慢,请更换 |
| 请求成功率 | 成功请求的百分比(HTTP 200-299) | <85% — 代理或机器人逻辑存在问题 |
| 代理的工作时间 | 代理在没有问题的情况下使用的时间 | <24 小时 — 可能 IP 被封禁 |
示例日志系统
# Python - 高级日志记录与指标
import logging
import time
from collections import defaultdict
import json
class BotMonitor:
def __init__(self):
self.metrics = {
'requests_total': 0,
'requests_success': 0,
'errors_429': 0,
'errors_403': 0,
'errors_other': 0,
'proxy_switches': 0,
'avg_latency': []
}
self.proxy_stats = defaultdict(lambda: {
'requests': 0,
'errors': 0,
'last_error': None
})
# 设置日志记录器
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('bot_monitor.log'),
logging.StreamHandler()
]
)
self.logger = logging.getLogger('BotMonitor')
def log_request(self, proxy, status_code, latency):
self.metrics['requests_total'] += 1
self.metrics['avg_latency'].append(latency)
self.proxy_stats[proxy]['requests'] += 1
if 200 <= status_code < 300:
self.metrics['requests_success'] += 1
elif status_code == 429:
self.metrics['errors_429'] += 1
self.proxy_stats[proxy]['errors'] += 1
self.logger.warning(f'代理 {proxy} 的速率限制')
elif status_code == 403:
self.metrics['errors_403'] += 1
self.proxy_stats[proxy]['errors'] += 1
self.proxy_stats[proxy]['last_error'] = time.time()
self.logger.error(f'代理 {proxy} 被封禁(403)')
else:
self.metrics['errors_other'] += 1
self.logger.error(f'代理 {proxy} 的错误 {status_code}')
def log_proxy_switch(self, old_proxy, new_proxy):
self.metrics['proxy_switches'] += 1
self.logger.info(f'代理切换:{old_proxy} -> {new_proxy}')
def get_report(self):
total = self.metrics['requests_total']
if total == 0:
return "没有数据"
success_rate = (self.metrics['requests_success'] / total) * 100
avg_latency = sum(self.metrics['avg_latency']) / len(self.metrics['avg_latency'])
report = f"""
=== 机器人监控报告 ===
总请求数:{total}
成功请求:{self.metrics['requests_success']} ({success_rate:.1f}%)
429 错误(速率限制):{self.metrics['errors_429']}
403 错误(封禁):{self.metrics['errors_403']}
其他错误:{self.metrics['errors_other']}
平均延迟:{avg_latency:.0f}ms
代理切换次数:{self.metrics['proxy_switches']}
=== 代理统计 ===
"""
for proxy, stats in self.proxy_stats.items():
error_rate = (stats['errors'] / stats['requests'] * 100) if stats['requests'] > 0 else 0
report += f"{proxy}: {stats['requests']} 次请求, {stats['errors']} 次错误 ({error_rate:.1f}%)\n"
return report
通过监控这些指标,您可以及时发现问题并采取措施,确保机器人在 Discord 上的稳定运行。
结论
设置代理以防止 Discord 封禁是一个复杂但必要的过程。通过理解 Discord 的保护机制、选择合适的代理类型、实施有效的 IP 轮换策略以及监控机器人的表现,您可以大大降低被封禁的风险。遵循本指南中的建议,您将能够更有效地管理 Discord 机器人并确保其长期稳定运行。