DNF 私服终极整合镜像部署教程:网关+五国+假人+SSH+进度条看板 一包全带走
本文是《DNF 私服终极整合镜像部署教程(基础部署篇)》的实战续篇:记录从”容器跑起来”到”全链路真绿”踩过的 9 个真实大坑,并给出 DOF_SERVER_IP 环境变量一键换机 与 一键体检修复脚本。看完这篇,换服务器不再靠碰运气。
一、为什么换台服务器要改这么多东西
整合镜像是”整包搬运”:MySQL 数据、频道配置、假人配置、网关密钥全部随卷迁移。但老服务器的 IP 和环境差异会残留在三个层面,任何一层没改干净,就会出现”看起来都绿了、玩家进不来 / 后台空白”的薛定谔状态:
| 层面 | 文件/位置 | 典型症状 |
|---|---|---|
| 频道层 | /home/neople/game/cfg/siroco*.cfg(19 个文件) | 客户端列表”IP 不符” |
| 系统层 | /etc/my.cnf、sudo、net-tools、profile | 备份失败 / 网关死循环 / SSH 白板 |
| 组件层 | robot 启动方式、MySQL 表名大小写 | 假人不动 / 暴雨后台空白 |
二、环境变量版部署:换机只改一行
在 docker-compose.yml 里声明服务器 IP,容器每次启动自动统一频道配置:
services:
dof:
image: dof:v5
container_name: dof
network_mode: host
cap_add:
- SYS_NICE
shm_size: 2g
restart: unless-stopped
environment:
DOF_SERVER_IP: 1.2.3.4 # ← 换服务器只改这一行
volumes:
- dof-mysql:/var/lib/mysql
- dof-neople:/home/neople
- dof-root:/root
- dof-dp2:/home/dp2
volumes:
dof-mysql: {}
dof-neople: {}
dof-root: {}
dof-dp2: {}
启动脚本的自动换 IP 逻辑
在 entrypoint 启动 MySQL 之前加一段(逻辑已实测;老部署手动执行同样有效):
# 自动发现 cfg 里的旧公网 IP 并整体替换(幂等,可重复执行)
if [ -n "$DOF_SERVER_IP" ]; then
CUR=$(grep -rohE '([0-9]{1,3}\.){3}[0-9]{1,3}' /home/neople/game/cfg/siroco*.cfg \
| grep -vE '^(0\.|127\.|10\.|192\.168\.)' \
| sort | uniq -c | sort -rn | head -1 | awk '{print $2}')
if [ -n "$CUR" ] && [ "$CUR" != "$DOF_SERVER_IP" ]; then
sed -i "s/$CUR/$DOF_SERVER_IP/g" /home/neople/game/cfg/siroco*.cfg
echo "[IP] 频道配置 $CUR -> $DOF_SERVER_IP 完成"
fi
fi
原理:不硬编码旧 IP,而是统计 cfg 里出现频率最高的公网 IP 自动识别再整体替换。换第 N 台服务器只改 compose 里的 DOF_SERVER_IP,docker restart dof 即生效(cfg 在 dof-neople 卷里持久保留)。
三、九大踩坑实录(症状 → 真相 → 修复)
坑 1SSH 登录上去什么都没有
原因:centos:7 基础镜像 root 没有 .bash_profile,登录 shell 根本不读 .bashrc,看板自然不出现。
修复:把 profile 文件写进 dof-root 卷。注意 SSH 目录挂的是卷,镜像里的文件会被卷遮住——这是 docker 卷最经典的坑。
原因:centos:7 基础镜像 root 没有 .bash_profile,登录 shell 根本不读 .bashrc,看板自然不出现。
修复:把 profile 文件写进 dof-root 卷。注意 SSH 目录挂的是卷,镜像里的文件会被卷遮住——这是 docker 卷最经典的坑。
坑 2y 菜单备份失败:sudo: command not found
原因:镜像没装 sudo,MySQL 客户端工具不在 PATH。
修复:
原因:镜像没装 sudo,MySQL 客户端工具不在 PATH。
修复:
yum install -y sudo net-tools
ln -sf /usr/local/mysql/bin/mysqldump /usr/local/mysql/bin/mysql /usr/local/mysql/bin/mysqladmin /usr/bin/
mkdir -p /root/mysqlbak
坑 3客户端列表提示”IP 不符”
原因:19 个 siroco*.cfg 里写的是老服务器 IP。
修复:一条命令统一替换(改完重启五国或容器生效):
原因:19 个 siroco*.cfg 里写的是老服务器 IP。
修复:一条命令统一替换(改完重启五国或容器生效):
sed -i 's/老IP/新IP/g' /home/neople/game/cfg/siroco*.cfg
# 或在 compose 里配 DOF_SERVER_IP 后 docker restart dof
坑 4数据库链接失败:Could not open required defaults file: /etc/my.cnf
原因:容器里没有 my.cnf;且 mysql 要求配置文件权限 600,权限不对会被静默忽略。
修复:
原因:容器里没有 my.cnf;且 mysql 要求配置文件权限 600,权限不对会被静默忽略。
修复:
cat > /etc/my.cnf <<'EOF'
[client]
port=3306
socket=/tmp/mysql.sock
[mysqld]
basedir=/usr/local/mysql
datadir=/var/lib/mysql
socket=/tmp/mysql.sock
user=mysql
port=3306
lower_case_table_names=1
EOF
chmod 600 /etc/my.cnf
注意最后的 lower_case_table_names=1,它是坑 8 的解药。
坑 5网关死循环:Gateway.log 两万条 “Gateway Restart…”
原因:Gatewayd 是网关保活器,内嵌 netstat 探测 8188;容器里没有 net-tools,探测永远失败,每五秒”重启”一次,登录列表永远出不来。
修复:
原因:Gatewayd 是网关保活器,内嵌 netstat 探测 8188;容器里没有 net-tools,探测永远失败,每五秒”重启”一次,登录列表永远出不来。
修复:
yum install -y net-tools,验证:tail -f /root/Gateway.log 应持续输出 Gateway run ok!。教训:看板绿色只代表端口在听,必须看组件日志。坑 6robot 看似在跑其实早死了(僵尸进程假活)
原因:robot 崩溃后变僵尸进程(Z/defunct),容器 PID 1 不回收;启动脚本用 pgrep 判活,把僵尸当活进程,永远”跳过启动”。
修复:启动脚本改用端口检测判活:
原因:robot 崩溃后变僵尸进程(Z/defunct),容器 PID 1 不回收;启动脚本用 pgrep 判活,把僵尸当活进程,永远”跳过启动”。
修复:启动脚本改用端口检测判活:
if ss -tln 2>/dev/null | grep -q ':8112 '; then
echo "robot已在运行,跳过"; exit 0
fi
cd /root
setsid nohup /root/robot >> /var/log/robot.log 2>&1 &
坑 7robot 管理台”数据库:错误 / 密钥:错误”
原因:带
修复:用坑 6 的裸跑命令。裸跑后自动建 4 条 MySQL 连接、20 条游戏服连接并开放 8111 API。
原因:带
--web-admin 参数启动会进入显式管理模式,触发密钥校验链;正确方式是无参数裸跑,让 robot 自己读 /root/config/conf/config.ini(端口/密码/数据库全在里面)。修复:用坑 6 的裸跑命令。裸跑后自动建 4 条 MySQL 连接、20 条游戏服连接并开放 8111 API。
坑 8MySQL 大小写敏感:组件全部读空表
原因:原生组件的 SQL 全用大写表名(如
修复:按坑 4 写入含该配置的 my.cnf 后
原因:原生组件的 SQL 全用大写表名(如
d_baoyu.Robot),迁移时 robot 程序建的是小写表。老服务器 MySQL 配了 lower_case_table_names=1(大小写折叠),新容器没配,大写查询读到的全是独立空表。修复:按坑 4 写入含该配置的 my.cnf 后
docker restart dof。若重启报表名冲突,先删大写空表:mysql -ugame -p'你的数据库密码' -e "drop table if exists d_baoyu.Robot, d_baoyu.Robot_stall, d_baoyu.Robot_stall_config, d_baoyu.dataTmp"
坑 9暴雨后台全空白,提示”检查网关是否启动!”
真相:后台走 8188 管理协议,周期发握手包,网关侧验证链不过就拒绝下发数据。成立条件是完整一条链:net-tools 修好网关保活(坑5)→ robot 裸跑并开放 8111 API(坑6/7)→ 大小写折叠让组件读得到表(坑8)→ 全链重启,缺一环就空白。排障利器是直接看协议交互:
真相:后台走 8188 管理协议,周期发握手包,网关侧验证链不过就拒绝下发数据。成立条件是完整一条链:net-tools 修好网关保活(坑5)→ robot 裸跑并开放 8111 API(坑6/7)→ 大小写折叠让组件读得到表(坑8)→ 全链重启,缺一环就空白。排障利器是直接看协议交互:
tcpdump -ni any -s0 port 8188 -A | grep -a '<hz>'
四、一键体检修复脚本
把以上所有检测与修复收敛成一个脚本。SSH 进容器保存为 /root/check-dof.sh,以后每次换机/重启后跑一遍即可:
#!/bin/bash
# ===== DOF 全链体检修复 =====
G='\033[32;1m';R='\033[31;1m';Y='\033[33;1m';F='\033[0m'
ok(){ echo -e "$G[OK]$F $1"; }; bad(){ echo -e "$R[!!]$F $1"; }; fix(){ echo -e "$Y[修复]$F $1"; }
echo "── [1] SSH 看板文件"
[ -f /root/.bash_profile ] && [ -f /root/.bashrc ] && ok "profile 就绪" || bad "缺 profile 文件"
echo "── [2] sudo / mysql 工具 / 备份目录"
command -v sudo >/dev/null || { yum install -y sudo >/dev/null 2>&1 && fix "已装 sudo"; }
[ -x /usr/bin/mysqldump ] || { ln -sf /usr/local/mysql/bin/mysqldump /usr/local/mysql/bin/mysql /usr/local/mysql/bin/mysqladmin /usr/bin/; fix "已建 mysql 命令链接"; }
mkdir -p /root/mysqlbak && ok "备份目录就绪"
echo "── [3] 频道 cfg 统一 IP"
IP=$(grep -rohE '([0-9]{1,3}\.){3}[0-9]{1,3}' /home/neople/game/cfg/siroco*.cfg 2>/dev/null | grep -vE '^(0\.|127\.|10\.|192\.168\.)' | sort | uniq -c | sort -rn | head -1 | awk '{print $2}')
echo " 当前 cfg IP: ${IP:-未识别}(不符则: sed -i 's/旧IP/新IP/g' /home/neople/game/cfg/siroco*.cfg)"
echo "── [4] /etc/my.cnf(含大小写折叠)"
grep -q 'lower_case_table_names=1' /etc/my.cnf 2>/dev/null && ok "my.cnf 就绪" || bad "需按坑4重建 my.cnf"
echo "── [5] net-tools(网关保活依赖)"
command -v netstat >/dev/null && ok "net-tools 就绪" || { yum install -y net-tools >/dev/null 2>&1 && fix "已装 net-tools"; }
echo "── [6] robot 进程(裸跑 + 端口检测)"
ss -tln | grep -q ':8112 ' && ok "robot Web 在线" || { bash /root/robot-start.sh && fix "已拉起 robot"; }
ss -tln | grep -q ':8111 ' && ok "robot API 8111 在线" || bad "8111 未监听,确认 robot 为无参数裸跑"
echo "── [7] 网关探测"
tail -5 /root/Gateway.log 2>/dev/null | grep -q 'run ok' && ok "网关 run ok" || bad "网关异常,看 /root/Gateway.log"
echo "── [8] MySQL 大小写折叠"
DBPASS=$(awk -F' = ' '/db_password/{print $2;exit}' /root/config.ini)
LC=$(mysql -ugame -p"$DBPASS" -N -e "show variables like 'lower_case_table_names'" 2>/dev/null | awk '{print $2}')
[ "$LC" = "1" ] && ok "lower_case_table_names=1" || bad "当前=$LC,需改 my.cnf 后重启容器"
echo "── [9] 假人数据"
CNT=$(mysql -ugame -p"$DBPASS" -N -e "select count(*) from d_baoyu.robot" 2>/dev/null)
[ "$CNT" -ge 1 ] 2>/dev/null && ok "robot 表 $CNT 行" || bad "robot 表读取异常"
echo "──── 体检完成:标[!!]项按本文对应坑位修复,改 my.cnf 后需 docker restart dof ────
五、排查方法论(比结论更值钱)
| 手法 | 命令 | 适用 |
|---|---|---|
| 协议抓包 | tcpdump -ni any -s0 port 8188 -A | 自定义 TCP 协议(后台/登录器)交互可视化 |
| SQL 行为日志 | SET GLOBAL general_log=1; log_output=’TABLE’ | 看组件到底查了哪张表 |
| 双机对照 | 同一模拟脚本分别打两台 | 快速判定”数据问题”还是”环境问题” |
| 进程视角 | ls -l /proc/进程ID/fd 配合 readlink | 看二进制运行时实际读了哪些文件 |
| md5 三连 | md5sum 二进制 + 配置 + 数据行数 | 排除”版本/数据不同”的猜测 |
六、运维速查
| 操作 | 命令 |
|---|---|
| 重启全部(配置/IP 生效) | docker restart dof |
| 只重启五国(约10分钟) | /root/dof-restart.sh |
| 假人管理台 | http://服务器IP:8112(裸跑模式,端口/密码读 conf/config.ini) |
| 网关保活日志 | tail -f /root/Gateway.log |
| 体检修复 | bash /root/check-dof.sh |
基础部署(镜像导入、首跑、看板、y 菜单)请回主教程:DNF 私服终极整合镜像部署教程:网关+五国+假人+SSH+进度条看板 一包全带走。两篇配合,从零到全绿、从全绿到换机不断档。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END




暂无评论内容