第 11 章:故障排查
第 11 章:故障排查
当 IRC 服务器出现问题时,系统化的排查方法是快速恢复的关键。本章整理了最常见的故障场景及其诊断方案。
11.1 故障排查流程
开始排查
│
├── 1. 确认故障现象
│ ├── 能否连接?
│ ├── 能否认证?
│ ├── 能否加入频道?
│ └── 能否发送消息?
│
├── 2. 检查服务端状态
│ ├── 进程是否运行?
│ ├── 端口是否监听?
│ ├── 配置文件是否正确?
│ └── 磁盘/内存是否足够?
│
├── 3. 检查网络
│ ├── 防火墙规则?
│ ├── DNS 解析?
│ └── TLS 证书?
│
├── 4. 查看日志
│ ├── 服务端日志
│ ├── 系统日志
│ └── 客户端日志
│
└── 5. 定位并修复
└── 验证修复 → 结束
11.2 连接问题
11.2.1 无法连接到服务器
症状: 客户端显示 “Connection refused” 或 “Connection timed out”
诊断步骤:
# 1. 检查进程
ps aux | grep -E 'ergo|unrealircd|inspircd'
systemctl status ergo
# 2. 检查端口监听
ss -tlnp | grep -E '6697|6667|8080'
# 如果没有输出,说明服务未监听
# 3. 检查防火墙
sudo iptables -L -n | grep -E '6697|6667'
sudo ufw status
# 4. 本地连接测试
openssl s_client -connect localhost:6697 -brief
# 或
telnet localhost 6697
# 5. 远程连接测试
nc -zv your-server-ip 6697
常见原因与解决方案:
| 原因 | 症状 | 解决方案 |
|---|---|---|
| 服务未启动 | Connection refused | systemctl start ergo |
| 端口未开放 | Connection timed out | ufw allow 6697/tcp |
| 配置错误 | 服务启动失败 | 检查配置语法 |
| 地址绑定错误 | 本地可连远程不行 | 检查 listen 配置中的 IP |
| DNS 解析失败 | Unknown host | 检查 DNS 记录 |
11.2.2 TLS 握手失败
症状: “SSL handshake failed” 或 “Certificate error”
# 1. 测试 TLS 连接
openssl s_client -connect irc.example.com:6697 \
-servername irc.example.com
# 2. 检查证书有效性
openssl x509 -in /path/to/server.crt -text -noout
# 3. 检查证书过期
openssl x509 -in /path/to/server.crt -enddate -noout
# 4. 检查证书与私钥匹配
openssl x509 -noout -modulus -in server.crt | md5sum
openssl rsa -noout -modulus -in server.key | md5sum
# 两个 md5sum 应该一致
# 5. 检查证书链
openssl verify -CAfile chain.pem server.crt
# 6. 检查 TLS 版本
openssl s_client -connect irc.example.com:6697 -tls1_2
openssl s_client -connect irc.example.com:6697 -tls1_3
常见 TLS 问题:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 自签名证书不被信任 | 客户端不信任 CA | 安装 Let’s Encrypt 证书 |
| 证书过期 | 证书有效期到了 | certbot renew |
| 主机名不匹配 | CN/SAN 与域名不一致 | 重新申请正确域名的证书 |
| 私钥权限 | 服务端无法读取私钥 | chmod 600 server.key |
| 协议版本不匹配 | 客户端/服务端 TLS 版本不同 | 配置支持 TLS 1.2+ |
11.2.3 SASL 认证失败
症状: “SASL authentication failed” 或 “Password incorrect”
# 1. 检查 NickServ 密码
# 在 IRC 客户端中
/NS IDENTIFY mypassword
# 2. 检查 SASL 配置(Weechat)
/set irc.server.example.*
# 3. 检查服务包日志
tail -f /opt/anope/logs/services.log | grep -i sasl
# 4. 手动测试 SASL
# 生成 PLAIN 认证字符串
echo -ne '\0alice\0mypassword' | base64
# 输出: AGFsaWNlAG15cGFzc3dvcmQ=
# 5. 检查 SASL 机制是否支持
# 连接时发送
CAP LS 302
# 查看服务器返回的 sasl 机制列表
常见 SASL 问题:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 密码错误 | 输入了错误的密码 | 重置密码 /NS SET PASSWORD |
| 机制不支持 | 客户端与服务器机制不匹配 | 检查支持的 SASL 机制 |
| 证书未注册 | EXTERNAL 模式未添加证书 | /NS CERT ADD |
| 服务包未运行 | NickServ 未在线 | 检查 Anope/Atheme 状态 |
11.3 服务器运行问题
11.3.1 服务启动失败
# 1. 查看启动错误
journalctl -u ergo --no-pager -n 50
# 或
tail -50 /opt/ergo/logs/ergo.log
# 2. 验证配置文件
# UnrealIRCd
/opt/unrealircd/unrealircd configtest
# InspIRCd
/opt/inspircd/bin/inspircd --configtest
# Ergo(手动启动观察输出)
./ergo run --config ergo.yaml
# 3. 检查文件权限
ls -la /opt/ergo/
ls -la /opt/ergo/ergo.yaml
ls -la /opt/ergo/certs/
# 4. 检查端口冲突
ss -tlnp | grep :6697
# 如果被其他进程占用
lsof -i :6697
常见启动失败原因:
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
Address already in use | 端口被占用 | 杀死占用进程或更换端口 |
Permission denied | 权限不足 | 检查文件权限 |
Cannot open config | 配置文件不存在 | 检查路径 |
Invalid syntax | 配置语法错误 | 修正配置 |
Certificate not found | TLS 证书缺失 | 检查证书路径 |
Database locked | 数据库被锁定 | 删除 .lock 文件 |
11.3.2 服务器内存占用过高
# 1. 检查进程内存
ps aux | grep ergo | awk '{print $2, $4, $6, $11}'
# 或使用 top/htop
# 2. 检查连接数
ss -tnp | grep :6697 | wc -l
# 3. 检查日志文件大小
du -sh /opt/ergo/logs/*
# 4. 配置内存限制(Docker)
# docker-compose.yml
# mem_limit: 512m
优化建议:
# Ergo 内存优化配置
limits:
max-connections-per-ip: 3
# 限制频道数
channels-per-client: 50
# 减少历史记录
away-count: 3
whowas-entries: 5
11.3.3 频道/用户数据丢失
# 1. 检查数据库文件
ls -la /opt/ergo/data/ergo.db
# 2. 检查最近备份
ls -lt /opt/backups/ergo/
# 3. 恢复备份
systemctl stop ergo
cp /opt/backups/ergo/ergo_latest.db /opt/ergo/data/ergo.db
systemctl start ergo
# 4. 检查文件系统
df -h
11.4 网络问题
11.4.1 服务器互联失败
# 1. 检查互联端口
ss -tlnp | grep :6900
# 2. 测试互联连接
openssl s_client -connect other-server:6900
# 3. 检查互联配置
# UnrealIRCd
grep -A 10 'link' /opt/unrealircd/conf/unrealircd.conf
# 4. 检查密码是否匹配
# 两端的 link password 必须一致
# 5. 检查 SID 是否冲突
# 每个服务器的 SID 必须唯一
互联问题排查清单:
| 检查项 | 状态 | 说明 |
|---|---|---|
| 互联端口开放 | ☐ | 6900/TCP |
| TLS 证书有效 | ☐ | 双方证书有效 |
| 密码一致 | ☐ | link password 一致 |
| SID 唯一 | ☐ | 不同 SID |
| 防火墙规则 | ☐ | 允许互联 IP |
| DNS 解析 | ☐ | 服务器名解析正确 |
11.4.2 DNS 问题
# 1. 检查 DNS 解析
dig irc.example.com A
dig irc.example.com AAAA
dig _irc._tcp.example.com SRV
# 2. 检查反向解析
dig -x your-server-ip
# 3. 测试 DNS 传播
nslookup irc.example.com 8.8.8.8
nslookup irc.example.com 1.1.1.1
# 4. 检查 hosts 文件
cat /etc/hosts | grep irc
11.4.3 IPv6 连接问题
# 1. 检查 IPv6 支持
ip -6 addr show
# 2. 测试 IPv6 连接
telnet -6 irc.example.com 6697
# 3. 检查 IPv6 监听
ss -tlnp | grep -6
# 4. 临时禁用 IPv6
sysctl -w net.ipv6.conf.all.disable_ipv6=1
11.5 调试工具
11.5.1 命令行调试工具
| 工具 | 用途 | 命令 |
|---|---|---|
openssl s_client | TLS 调试 | openssl s_client -connect host:6697 |
nc / ncat | TCP 连接测试 | nc -v host 6697 |
nmap | 端口扫描 | nmap -p 6697 host |
tcpdump | 抓包分析 | tcpdump -i eth0 port 6697 |
wireshark | 图形化抓包 | GUI 工具 |
strace | 系统调用跟踪 | strace -p <pid> |
lsof | 打开文件查看 | lsof -i :6697 |
dig | DNS 查询 | dig irc.example.com |
curl | HTTP 测试 | curl -v https://irc.example.com |
journalctl | systemd 日志 | journalctl -u ergo -f |
11.5.2 手动 IRC 协议调试
# 使用 netcat 手动发送 IRC 命令
{
echo "NICK testbot"
echo "USER testbot 0 * :Test Bot"
sleep 2
echo "JOIN #test"
sleep 2
echo "PRIVMSG #test :Hello, world!"
sleep 5
echo "QUIT :Testing"
} | openssl s_client -connect irc.example.com:6697 -quiet
11.5.3 IRC 内置调试命令
/* Oper 调试命令 */
/REHASH /* 重载配置 */
/CONNECT <server> /* 连接到服务器 */
/SQUIT <server> /* 断开服务器 */
/TIME /* 查看服务器时间 */
/TRACE <target> /* 跟踪路由 */
/WHOWAS <nick> /* 历史用户查询 */
/LUSERS /* 服务器统计 */
/LINKS /* 服务器拓扑 */
/MAP /* 服务器地图 */
11.5.4 Weechat 调试
# 启用 Weechat 调试日志
/export DEBUG 1
# 查看服务器原始消息
/set irc.look.debug_raw 1
# 查看 SASL 调试
/set irc.server.example.sasl_timeout 60
11.6 日志分析
11.6.1 常见日志模式
# 搜索连接错误
grep -i 'error\|failed\|denied' /opt/ergo/logs/ergo.log
# 统计连接数
grep 'Client connected' /opt/ergo/logs/ergo.log | wc -l
# 查找断开连接
grep 'Client disconnected' /opt/ergo/logs/ergo.log
# 查看封禁
grep -i 'kline\|gline\|zline\|shun' /opt/ergo/logs/ergo.log
# 统计错误频率
grep -c 'ERROR' /opt/ergo/logs/ergo.log
# 实时监控
tail -f /opt/ergo/logs/ergo.log | grep --color -E 'error|warn|fail'
# 按时间段过滤
grep '2026-05-10' /opt/ergo/logs/ergo.log
11.6.2 日志级别调整
# Ergo 临时调整日志级别
logging:
- method: "file"
filename: "/opt/ergo/logs/ergo.log"
level: "debug" # 临时设为 debug
11.7 常见问题 FAQ
Q1: 用户无法注册昵称
症状: /NS REGISTER 返回 "Registration is disabled"
原因: 配置中禁用了注册
解决:
# Ergo
accounts:
registration:
enabled: true
# Anope
nickserv {
registration yes
}
Q2: 频道模式不生效
症状: 设置了 +m 但非成员仍能发言
原因: 模式设置不正确,或有 +n 外的权限冲突
排查:
/mode #channel # 查看当前模式
/mode #channel +mn # 同时设置 +m 和 +n
Q3: 服务器占用 CPU 100%
症状: CPU 使用率持续 100%
可能原因:
- 死循环脚本/Bot
- 大量并发连接
- 配置错误导致的循环
排查:
top -c | grep ergo
strace -p <pid> -c # 统计系统调用
# 检查是否有异常 Bot
Q4: 用户被莫名封禁
症状: 用户报告无法连接
排查:
# 查看服务器封禁列表
/STATS k # K-lines
/STATS g # G-lines
/STATS z # Z-lines
# 检查 fail2ban
sudo fail2ban-client status ircd
# 检查 IP 是否被封
sudo iptables -L -n | grep <user-ip>
Q5: 桥接 Bot 消息延迟
症状: 桥接消息延迟 10 秒以上
可能原因:
- 网络延迟
- 桥接进程资源不足
- API 速率限制
排查:
# 检查桥接进程
docker logs matterbridge --tail 50
# 检查网络延迟
ping bridge-server
# 检查速率限制日志
grep 'rate limit' /var/log/matterbridge.log
Q6: WebSocket 连接失败
症状: Web 客户端无法通过 WebSocket 连接
排查:
# 检查 WebSocket 端口
ss -tlnp | grep 8443
# 测试 WebSocket
wscat -c wss://irc.example.com:8443
# 检查 Nginx 配置
nginx -t
11.8 性能优化
11.8.1 连接优化
# Ergo 性能配置
server:
# 启用 TCP Fast Open
# (需要系统支持)
# tor-enabled: false
limits:
# 限制连接数
max-connections-per-ip: 3
# 减少资源占用
channels-per-client: 50
away-count: 3
whowas-entries: 5
11.8.2 系统级优化
# 增加文件描述符限制
echo "ergo soft nofile 65536" >> /etc/security/limits.conf
echo "ergo hard nofile 65536" >> /etc/security/limits.conf
# 优化内核参数
cat >> /etc/sysctl.conf << EOF
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
EOF
sysctl -p
11.9 ⚠️ 注意事项
| 事项 | 说明 |
|---|---|
| 修改前备份 | 修改任何配置前先备份 |
| 逐项排查 | 一次只改一个变量 |
| 记录变更 | 记录所有配置变更 |
| 灰度发布 | 重大变更先在测试环境验证 |
| 及时更新 | 关注安全公告并及时更新 |
| 监控告警 | 配置监控和告警系统 |
扩展阅读
下一章: 第 12 章:最佳实践 — 运维规范、社区管理、备份策略和性能优化。