> 🎯 本工具帮助你在 Linux 服务器上**一键部署** DNF 游戏服务端,全程只需要改一个配置文件、敲几条命令。 > > 即使你不懂 Docker,也能轻松完成。 > --- ## 📖 目录 + [你需要准备什么](#你需要准备什么) + [目录结构一览](#目录结构一览) + [快速开始(4 步完成部署)](#快速开始4-步完成部署) - [第一步:上传并解压](#第一步上传并解压) - [第二步:修改配置文件](#第二步修改配置文件) - [第三步:执行部署脚本](#第三步执行部署脚本) - [第四步:观察启动日志,确认部署成功](#第四步观察启动日志确认部署成功) + [日常运维](#日常运维) - [停止服务](#停止服务) - [启动服务](#启动服务) - [卸载服务](#卸载服务) - [密钥轮换(建议部署后执行)](#密钥轮换建议部署后执行) - [单独查看日志](#单独查看日志) + [配置文件详解](#配置文件详解) + [架构与原理(可选阅读)](#架构与原理可选阅读) - [整体架构图](#整体架构图) - [部署流程图](#部署流程图) - [启动流程图](#启动流程图) - [容器之间的关系](#容器之间的关系) - [数据持久化](#数据持久化) + [常见问题](#常见问题) + [注意事项](#注意事项) --- ## 你需要准备什么 | 条件 | 说明 | | --- | --- | | **一台 Linux 服务器** | CentOS 7/8、Ubuntu 18+ 等主流发行版均可 | | **已安装 Docker** | 容器引擎,用来运行游戏服务 | | **已安装 Docker Compose** | 容器编排工具,用来管理多个容器。Docker 较新版本自带(`docker compose`),旧版需单独安装(`docker-compose`) | | **服务器内存 ≥ 2G** | 推荐 4G 及以上,内存越大越流畅。**如果物理内存不足(如只有 2G),必须开启虚拟内存(swap)**,具体教程请自行搜索「Linux 开启 swap」 | | **镜像文件已就位** | `image/` 目录下需要有 `dnf-mysql-5.6.tar` 和 `dnf-server-s2.tar` 两个镜像文件 | > ⚠️ **前提条件**:服务器上必须已经安装好 **Docker** 和 **Docker Compose**,本文档不负责指导安装。 > > + **云服务器**(如腾讯云、阿里云):在控制台创建实例时,可以直接选择预装 Docker 的系统镜像,开箱即用。 > + **虚拟机 / 物理机**:请自行搜索「CentOS 安装 Docker」或「Ubuntu 安装 Docker」,网上教程很多。 > --- ## 目录结构一览 解压 `server.tar.gz` 后,你会在当前目录得到以下文件结构: ```plain ├── README.md ← 📄 你正在看的这个文档 ├── config/ │ └── vm.cfg ← ⚙️ 【唯一需要你修改的文件】配置文件 ├── image/ │ ├── dnf-mysql-5.6.tar ← 📦 MySQL 数据库镜像 │ └── dnf-server-s2.tar ← 📦 游戏服务端镜像 └── script/ ├── deploy.sh ← 🚀 一键部署脚本(首次使用) ├── start.sh ← ▶️ 启动脚本(日常启动) ├── stop.sh ← ⏹️ 停止脚本(日常停止) ├── remove.sh ← 🗑️ 卸载脚本(删除容器) ├── rotate-key.sh ← 🔑 密钥轮换脚本(建议部署后执行一次) └── init-log.sh ← 📋 日志展示脚本(可单独使用) ``` > 你只需要关注 `config/vm.cfg` 这一个文件,其他的脚本直接运行就好。 > --- ## 快速开始(4 步完成部署) ### 第一步:上传并解压 1. 在服务器上新建一个**空目录**作为工作目录(名字随意,例如 `dnf`): ```bash mkdir -p /root/dnf ``` 2. 将 `server.tar.gz` 上传到这个空目录中。 > 💡 上传方式:可以用 FTP 工具(如 FileZilla、WinSCP)、`scp` 命令、宝塔面板等,选择你熟悉的方式即可。 > 3. 进入该目录并解压: ```bash cd /root/dnf tar -xzvf server.tar.gz ``` 解压后目录里就是 3 个文件夹 + 1 个 README 文档: ```plain /root/dnf/ ├── config/ ├── image/ ├── script/ └── README.md ``` > 后续所有操作都在此目录下进行。 > ### 第二步:修改配置文件 用编辑器打开 `config/vm.cfg`: ```bash vi config/vm.cfg ``` 文件内容如下,**每一项都要根据你的实际情况填写**: ```properties cpu核心数=2 包括虚拟内存的总内存大小(G)=8 game账户密码(8位)=uu5!^%jg root账户密码=88888888 服务访问ip=192.168.200.131 版本名称=s2a3 是否开启dp2和frida插件(true/false)=true 是否开启暴雨登录器网关(true/false)=true 是否开启s2服务端插件(true/false)=true 连接池大小(3-1000)=20 ``` > ⚠️ **重要**:只修改每行 **等号 **`=`** 后面**的值,等号及等号前面的内容是配置项名称,**不要修改**,否则脚本将无法正确解析配置。 > > ⚠️ 各项的含义请看下面的 [配置文件详解](#配置文件详解),**每一项都不能留空**。 > ### 第三步:执行部署脚本 ```bash cd script bash deploy.sh ``` 脚本会自动完成以下所有事情(你只需要等待): 1. ✅ 检查 Docker 和 Docker Compose 是否已安装 2. ✅ 读取你的配置文件 3. ✅ 加载 MySQL 和 Server 的 Docker 镜像 4. ✅ 创建 Docker 网络和数据卷 5. ✅ 生成 docker-compose.yml 编排文件 6. ✅ 启动 MySQL 容器,等待数据库初始化完成 7. ✅ 启动 Server 容器 8. ✅ 自动展示 Server 启动日志 > ⏳ **首次部署**时,MySQL 需要导入大量游戏数据库,可能需要 **5~30 分钟**(取决于服务器性能)。 Server 会自动等待 MySQL 就绪后才启动,不需要你手动干预。 > ### 第四步:观察启动日志,确认部署成功 部署脚本在启动容器后,会**自动展示 Server 的启动日志**,你可以实时看到加载进度: ```plain [INFO] 正在展示启动日志(Ctrl+C 退出)... [12:34:00] - Loading Skills Success [12:34:00] - Loading Items Success [12:34:09] - Loading Quests Success [12:34:09] - Loading Characters Success [12:34:15] GeoIP Allow Country Code : CN [12:34:15] GeoIP Allow Country Code : HK [12:34:15] GeoIP Allow Country Code : KR [12:34:15] GeoIP Allow Country Code : MO [12:34:15] GeoIP Allow Country Code : TW ``` > 看到 **5 个 GeoIP Allow Country Code**(俗称「五国」:CN、HK、KR、MO、TW)就说明**部署成功**了! > > 按 **Ctrl + C** 退出日志查看(不会影响服务运行)。 > --- ## 日常运维 部署完成后,后续的日常操作只需要用以下脚本: | 脚本 | 用途 | | --- | --- | | `start.sh` | 启动服务 | | `stop.sh` | 停止服务 | | `remove.sh` | 卸载容器(保留数据) | | `rotate-key.sh` | 密钥轮换(生成新的 RSA 密钥对,建议部署后执行) | | `init-log.sh` | 单独查看 Server 启动日志 | ### 停止服务 ```bash cd script bash stop.sh ``` 停止顺序:**先停 Server → 再停 MySQL**(脚本自动处理,保证数据安全)。 ### 启动服务 ```bash cd script bash start.sh ``` 启动顺序:**先启动 MySQL → 再启动 Server**(脚本自动处理)。 启动后,脚本会**自动展示游戏服务端的启动日志**,你可以实时看到加载进度: > 💡 如果只想单独查看日志(不启动容器),可以直接执行 `bash init-log.sh`。 > ```plain [INFO] 正在展示启动日志(Ctrl+C 退出)... [12:29:00] - Loading Skills Success [12:29:00] - Loading Items Success [12:29:09] - Loading Quests Success [12:29:09] - Loading Characters Success [12:29:00] GeoIP Allow Country Code : CN [12:29:00] GeoIP Allow Country Code : HK [12:29:00] GeoIP Allow Country Code : KR [12:29:00] GeoIP Allow Country Code : MO [12:29:00] GeoIP Allow Country Code : TW ``` > 看到 **5 个 GeoIP Allow Country Code**(俗称「五国」)就说明启动成功了! > > 按 **Ctrl + C** 退出日志查看(不会影响服务运行)。 > ### 卸载服务 ```bash cd script bash remove.sh ``` 卸载会**停止并删除容器**,但**保留数据卷**(游戏数据不丢失)。如需重新部署,再次执行 `deploy.sh` 即可。 如果要**彻底清除所有数据**(不可恢复),加 `--volumes` 参数: ```bash bash remove.sh --volumes ``` ### 密钥轮换(建议部署后执行) ```bash cd script bash rotate-key.sh ``` 生成新的 RSA 2048 密钥对,覆盖 server-data 数据卷中的密钥文件。执行后需要 `bash stop.sh` + `bash start.sh` 重启服务才能生效。 > ⚠️ **安全提示**:镜像中自带的默认密钥是所有人共用的,不替换也能正常运行,但存在安全风险(其他人可以用相同密钥伪造登录)。建议部署后执行一次密钥轮换。 > ### 单独查看日志 ```bash cd script bash init-log.sh ``` 直接展示 Server 当前的启动日志,适用于想确认服务状态但不想重启的场景。 --- ## 配置文件详解 配置文件路径:`config/vm.cfg` | 配置项 | 示例值 | 说明 | | --- | --- | --- | | `cpu核心数` | `2` | 你的服务器有几个 CPU 核心。不知道的话,在服务器上执行 `nproc` 查看 | | `包括虚拟内存的总内存大小(G)` | `8` | 服务器的总内存(单位:GB)。不知道的话,执行 `free -g` 查看 `total` 列。**包含虚拟内存(swap)** | | `game账户密码(8位)` | `uu5!^%jg` | 游戏数据库的 game 账户密码,**必须恰好 8 位**,否则游戏无法连接数据库 | | `root账户密码` | `88888888` | MySQL 数据库的 root 管理员密码,可以自定义 | | `服务访问ip` | `192.168.200.131` | 玩家连接游戏时使用的 IP 地址。如果是公网服务器,填公网 IP;如果是内网/局域网,填内网 IP | | `版本名称` | `s2a3` | 给这套部署起个名字。所有容器、数据卷都会以此为前缀(如 `s2a3-server`、`s2a3-mysql`)。如果你想在同一台服务器上部署多套,改成不同的名字即可(如 `s3a3`) | | `是否开启dp2和frida插件(true/false)` | `true` | DP2 插件开关。开启后支持 Lua/JS 脚本扩展游戏功能 | | `是否开启暴雨登录器网关(true/false)` | `true` | 暴雨登录器网关开关。开启后支持暴雨登录器连接 | | `是否开启s2服务端插件(true/false)` | `true` | 70s2 引擎与分辨率适配插件开关 | | `连接池大小(3-1000)` | `20` | TCP 连接池大小,取代 df_channel_r/df_bridge_r 硬编码的 1000 槽,可显著节省内存。单人玩填 3,小型服务器 10–20,中等部署 256,填 1000 等于禁用补丁 | > ⚠️ **关于内存配置**:`包括虚拟内存的总内存大小(G)` 填写的是你**打算分配给游戏服务端的总内存**(物理内存 + swap 虚拟内存)。如果填写的值大于实际可用内存,会导致 Server 容器启动失败(OOM)。例如物理内存 2G + swap 6G = 可填 8。 > > 💡 **关于版本名称**:这个名字决定了容器和数据卷的命名前缀。比如设置为 `s2a3`,那么: > > + MySQL 容器名 → `s2a3-mysql` > + Server 容器名 → `s2a3-server` > + 数据卷 → `s2a3-mysql-data`、`s2a3-server-log` 等 > > 你可以在同一台服务器上部署多个版本(如 `s2a3` 和 `s3a3`),它们互不干扰。 > --- ## 架构与原理(可选阅读) > 以下内容帮助你理解"脚本背后做了什么",**不看也不影响使用**。 > ### 整体架构图 ```plain ┌─────────────────────────────────────────────────────────┐ │ Linux 服务器 │ │ │ │ ┌─────────────────┐ ┌─────────────────────────┐ │ │ │ s2a3-mysql │ │ s2a3-server │ │ │ │ (MySQL 5.6) │◄──────│ (DNF 游戏服务端) │ │ │ │ │ 3306 │ │ │ │ │ 存储游戏数据 │ │ 运行游戏逻辑 │ │ │ └────────┬─────────┘ └────────┬────────────────┘ │ │ │ │ │ │ ┌─────▼─────┐ ┌───────▼──────────┐ │ │ │ mysql-data │ │ server-data │ │ │ │ mysql-conf │ │ server-log │ │ │ └───────────┘ └──────────────────┘ │ │ (数据卷:持久化存储,容器删了数据还在) │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ Docker 网络: dnf (172.20.0.0/16) │ │ │ │ 两个容器通过此网络互相通信 │ │ │ └─────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ │ 玩家通过 IP 连接 ``` ### 部署流程图 以下是从拿到压缩包到部署完成的完整流程: ```mermaid flowchart TD A0["新建空目录并上传 server.tar.gz"] --> A1["tar -xzvf server.tar.gz"] A1 --> A2["cd script"] A2 --> A["bash deploy.sh"] A --> B{"检查 Docker 环境"} B -- "Docker ✅ / Compose ✅" --> C["读取 config/vm.cfg"] B -- "有缺失 ❌" --> B1["报错退出,提示安装"] C --> D{"配置项是否完整?"} D -- "是" --> E["加载 Docker 镜像dnf-mysql-5.6.tardnf-server-s2.tar"] D -- "否" --> D1["报错退出,提示缺少哪项"] E --> F["创建 Docker 网络 dnf"] F --> G["创建 4 个数据卷mysql-data / mysql-confserver-data / server-log"] G --> H["根据配置生成docker-compose.yml"] H --> I["启动 MySQL 容器"] I --> J["MySQL 健康检查(等待初始化完成)"] J --> K["启动 Server 容器"] K --> L["展示 Server 启动日志"] L --> M["看到五国 → ✅ 部署成功!Ctrl+C 退出日志"] ``` ### 启动流程图 以下是执行 `start.sh` 时的流程: ```mermaid flowchart TD A["bash start.sh"] --> B["启动 MySQL 容器"] B --> C["启动 Server 容器"] C --> D["等待 Server 产生新日志"] D --> E["tail -f 展示启动日志"] E --> F["用户看到日志后按 Ctrl+C 退出"] ``` ### 容器之间的关系 ```mermaid flowchart LR subgraph MySQL容器 DB["MySQL 5.6端口 3306存储 21 个游戏数据库"] end subgraph Server容器 SRV["DNF 游戏服务端16 个子服务进程+ 网关 + 监控"] end SRV -- "读写游戏数据(通过 Docker 网络)" --> DB SRV -- "对外暴露端口20303 等" --> 玩家客户端 ``` **两个容器的分工**: | 容器 | 角色 | 类比 | | --- | --- | --- | | **MySQL 容器** | 数据库,存储所有游戏数据(角色、装备、账号等) | 相当于"仓库" | | **Server 容器** | 游戏服务端,运行游戏逻辑,处理玩家请求 | 相当于"工厂" | Server 依赖 MySQL,所以: + **启动时**:先启动 MySQL → 再启动 Server + **停止时**:先停止 Server → 再停止 MySQL ### 数据持久化 部署时会创建 4 个 **Docker 数据卷**,用来持久化存储数据。即使容器被删除重建,数据也不会丢失: | 数据卷 | 用途 | 说明 | | --- | --- | --- | | `{版本名称}-mysql-data` | MySQL 数据文件 | 所有游戏数据库的实际数据 | | `{版本名称}-mysql-conf` | MySQL 配置文件 | 数据库的自定义配置 | | `{版本名称}-server-data` | Server 数据文件 | 游戏脚本(pvf)、主程序、密钥、插件配置等(详见下方) | | `{版本名称}-server-log` | Server 日志文件 | 游戏运行日志,`start.sh` 展示的就是这里的日志 | > 💡 **简单理解**:数据卷就像一个"保险箱",容器是"工人"。工人可以换,但保险箱里的东西一直在。 > #### server-data 数据卷详细内容 `{版本名称}-server-data` 卷挂载到容器内的 `/data` 目录,包含以下可热更文件(修改后重启容器即生效): | 文件/目录 | 作用 | 修改场景 | | --- | --- | --- | | `Script.pvf` | 游戏脚本主文件(约 90MB) | 自定义游戏内容(技能、装备、地图等) | | `df_game_r` | 游戏服主程序(约 35MB) | 切换不同版本的服务端二进制 | | `publickey.pem` | 网关公钥 | 密钥轮换 | | `privatekey.pem` | 网关私钥 | 密钥轮换 | | `dp2/df_game_r.lua` | DP2 Lua 主脚本 | 编写/调试 DP2 插件功能 | | `dp2/df_game_r.js` | DP2 JS 脚本 | 编写/调试 DP2 插件功能 | | `dp2/frida_config.json` | DP2 Frida 配置 | 调整 DP2 插件配置 | | `config.ini` | 暴雨登录器网关配置 | 一般无需手动修改。容器启动时会自动从环境变量获取数据库地址、端口、账号、密码等配置 | | `so.cfg` | s2 插件 monitor 时间触发参数 | 调整攻城战/活动时间 | | `iteminfo.dat`(可选) | 拍卖行/点券物品信息 | 修复拍卖行搜索功能 | > 💡 **热更方式**:直接在宿主机上编辑数据卷中的文件,然后 `bash stop.sh` + `bash start.sh` 重启即可生效。 数据卷路径可通过 `docker volume inspect {版本名称}-server-data --format '{{.Mountpoint}}'` 查看。 > --- ## 常见问题 ### Q: 部署时卡在 MySQL 初始化很久,正常吗? **正常。** 首次部署时,MySQL 需要创建 21 个游戏数据库并导入大量 SQL 数据,根据服务器性能不同,可能需要 5~30 分钟。脚本设置了最长 30 分钟的等待时间,Server 会在 MySQL 完全就绪后才自动启动。 你可以在另一个终端窗口查看 MySQL 的实时日志: ```bash docker logs -f s2a3-mysql ``` ### Q: deploy.sh 报错"未检测到 Docker"怎么办? 说明你的服务器还没有安装 Docker 或 Docker Compose。云服务器(如腾讯云、阿里云)可以在控制台选择预装 Docker 的系统镜像;虚拟机请自行搜索安装教程。安装完成后重新执行 `deploy.sh`。 ### Q: 可以在同一台服务器上部署多套吗? **可以共存,但不能同时运行。** 修改 `vm.cfg` 中的 `版本名称` 为不同的值(如 `s2a3` 和 `s3a3`),然后分别执行 `deploy.sh`,每套部署的容器和数据卷都以版本名称为前缀,互不干扰。 但由于多个版本使用相同的端口(如 3306、20303),**同一时间只能运行一个版本**。想玩哪个版本,就先停掉当前运行的版本,再启动目标版本即可: ```bash # 停掉当前版本(假设正在运行 s2a3) bash stop.sh # 修改 vm.cfg 中的版本名称为 s3a3,然后启动 bash start.sh ``` ### Q: 停止后再启动,数据会丢失吗? **不会。** 所有游戏数据都保存在 Docker 数据卷中,停止/启动容器不会影响数据。 ### Q: start.sh 启动后日志一直在等待怎么办? 如果超过 120 秒仍未看到日志,可能是 Server 容器启动异常。请检查: ```bash # 查看 Server 容器状态 docker ps -a | grep server # 查看 Server 容器日志 docker logs s2a3-server ``` ### Q: 首次部署后进游戏连不上 / 没有频道怎么办? 首次执行 `deploy.sh` 时,Server 容器可能会出现 **core dump** 导致启动不完全成功(表现为游戏进去连不上服务器或者看不到频道)。这是正常现象,**直接停止再启动一次即可**: ```bash bash stop.sh bash start.sh ``` 看到「五国」日志输出后再进游戏,一般就正常了。 ### Q: game 账户密码可以随便设吗? **必须恰好 8 位字符**,这是游戏服务端的硬性限制。少于或多于 8 位都会导致游戏无法连接数据库。密码可以包含字母、数字和特殊字符。 --- ## 注意事项 1. **建议部署后轮换密钥**:执行 `bash rotate-key.sh` 生成你自己的密钥对,然后 `stop.sh` + `start.sh` 重启。镜像默认密钥所有人相同,不替换也能运行但存在安全风险 2. **首次部署请耐心等待**:MySQL 初始化需要时间,不要中途强制关闭终端或 Ctrl+C 中断 3. **不要手动修改 **`script/docker-compose.yml`:这个文件由 `deploy.sh` 自动生成,每次部署都会覆盖。如需调整参数,请修改 `config/vm.cfg` 后重新执行 `deploy.sh` 4. **game 密码必须 8 位**:这是硬性要求,不是建议 5. **服务访问 IP 要填对**:如果是云服务器,填公网 IP;如果是局域网,填局域网 IP。填错了玩家将无法连接 6. **停止和启动有顺序**:请使用 `stop.sh` 和 `start.sh` 脚本操作,不要直接用 `docker stop/start` 命令,脚本会保证正确的启停顺序 7. **重新部署会停止旧容器**:执行 `deploy.sh` 会先停止并删除同名的旧容器,然后创建新容器。数据卷中的数据不受影响 8. **镜像文件不要删**:`image/` 目录下的 `.tar` 文件是 Docker 镜像的离线包,首次部署时需要加载。加载完成后可以删除以节省磁盘空间,但建议保留备用 > 🎯 本工具帮助你**一键备份**和**恢复**游戏数据,支持手动备份、定时自动备份,操作简单,对小白友好。 > > 备份文件就是标准的 `.tar.gz` 压缩包,可以直接下载到本地保存。 > --- ## 📖 目录 + [备份了什么?](#备份了什么) + [命令一览](#命令一览) + [创建备份](#创建备份) + [查看备份列表](#查看备份列表) + [恢复备份](#恢复备份) + [导出备份到本地](#导出备份到本地) + [自动定时备份](#自动定时备份) - [开启定时备份(交互式)](#开启定时备份交互式) - [开启定时备份(快捷方式)](#开启定时备份快捷方式) - [查看定时备份状态](#查看定时备份状态) - [关闭定时备份](#关闭定时备份) - [修改定时备份配置](#修改定时备份配置) + [常见问题](#常见问题) + [注意事项](#注意事项) --- ## 备份了什么? 备份包含游戏的**全部核心数据**,恢复后游戏状态与备份时完全一致: | 数据卷 | 内容 | 包含什么 | | --- | --- | --- | | `{版本名称}-mysql-data` | MySQL 数据库 | 角色、装备、账号、仓库、拍卖行等所有游戏数据 | | `{版本名称}-server-data` | 服务端数据 | 游戏脚本(pvf)、主程序、密钥、插件配置等 | > 💡 备份文件是标准的 `.tar.gz` 压缩包,存放在 `backup/` 目录下,可以直接用 scp、FTP 等工具下载到本地保存。 > --- ## 命令一览 所有命令都在 `script/` 目录下执行: ```bash cd script bash backup.sh create # 创建备份 bash backup.sh list # 查看备份列表 bash backup.sh restore # 恢复备份(交互式选择) bash backup.sh cron-on # 开启自动定时备份 bash backup.sh cron-off # 关闭自动定时备份 bash backup.sh cron-status # 查看定时备份状态 bash backup.sh # 显示帮助信息 ``` --- ## 创建备份 ```bash cd script bash backup.sh create ``` 脚本会自动完成以下事情: 1. ⏹ 停止游戏容器(保证数据一致性) 2. 📦 打包两个数据卷为 `.tar.gz` 压缩包 3. ▶️ 重新启动游戏容器 4. ✅ 显示备份文件路径和大小 **输出示例**: ```plain [INFO] 开始创建备份(版本: s2a3)... [INFO] ⏹ 停止容器以确保数据一致性(游戏将短暂中断,备份完成后自动重启)... [INFO] 正在打包备份数据(数据量较大时可能需要几分钟,请耐心等待)... [INFO] MySQL 数据: /var/lib/docker/volumes/s2a3-mysql-data/_data [INFO] Server 数据: /var/lib/docker/volumes/s2a3-server-data/_data [INFO] ▶ 重新启动容器... [INFO] ✅ 备份完成! [INFO] 文件: /root/dnf/backup/s2a3_20260515_143000.tar.gz [INFO] 大小: 1.2 GB ``` > ⚠️ **备份期间游戏会短暂中断**(通常 1~5 分钟),备份完成后会自动重启。如果容器本来就是停止的,备份后不会自动启动。 > --- ## 查看备份列表 ```bash cd script bash backup.sh list ``` **输出示例**: ```plain [INFO] 备份列表(版本: s2a3) 序号 备份时间 文件大小 文件名 ────────────────────────────────────────────────────────────── 1 2026-05-15 14:30:00 1.2 GB s2a3_20260515_143000.tar.gz 2 2026-05-14 04:00:00 1.1 GB s2a3_20260514_040000.tar.gz 3 2026-05-13 04:00:00 1.1 GB s2a3_20260513_040000.tar.gz [INFO] 共 3 个备份,总占用 3.4 GB [INFO] 备份目录: /root/dnf/backup/ ``` > 列表按时间倒序排列,最新的备份在最前面。只显示当前版本的备份文件。 > --- ## 恢复备份 ### 方式一:交互式选择(推荐) ```bash cd script bash backup.sh restore ``` 脚本会先列出所有备份,你输入序号即可选择要恢复的备份: ```plain [INFO] 备份列表(版本: s2a3) 序号 备份时间 文件大小 文件名 ────────────────────────────────────────────────────────────── 1 2026-05-15 14:30:00 1.2 GB s2a3_20260515_143000.tar.gz 2 2026-05-14 04:00:00 1.1 GB s2a3_20260514_040000.tar.gz 请输入要恢复的备份序号: 1 ⚠️ 恢复将覆盖当前所有数据!此操作不可逆! ⚠️ 恢复后游戏状态将回到备份时的状态(角色、装备、金币等全部回档) 确认恢复? (y/N): y [INFO] 正在创建恢复前备份(后悔药,数据量较大时可能需要几分钟)... [INFO] ✅ 恢复前备份已创建: s2a3_20260515_150000_pre-restore.tar.gz (1.2 GB) [INFO] ⏹ 停止容器... [INFO] 正在恢复数据(数据量较大时可能需要几分钟,请耐心等待)... [INFO] 恢复 MySQL 数据... [INFO] 恢复 Server 数据... [INFO] ▶ 启动容器... [INFO] ✅ 恢复完成! [INFO] 已恢复备份: s2a3_20260515_143000.tar.gz [INFO] 恢复前备份: s2a3_20260515_150000_pre-restore.tar.gz ``` ### 方式二:指定文件名恢复 ```bash cd script bash backup.sh restore s2a3_20260515_143000.tar.gz ``` > 💡 **后悔药**:恢复前会自动创建一份当前数据的备份(文件名带 `_pre-restore` 标记)。万一恢复后发现不对,可以用这份备份再恢复回去。 > --- ## 导出备份到本地 备份文件就是普通的 `.tar.gz` 压缩包,直接下载即可: ```bash # 在你的本地电脑上执行(不是服务器上) scp root@你的服务器IP:/root/dnf/backup/s2a3_20260515_143000.tar.gz ./ ``` 也可以用 FTP 工具(FileZilla、WinSCP 等)连接服务器,进入 `backup/` 目录下载。 > 💡 建议定期将备份下载到本地或其他存储,防止服务器硬盘故障导致备份也丢失。 > --- ## 自动定时备份 ### 开启定时备份(交互式) ```bash cd script bash backup.sh cron-on ``` 脚本会一步步引导你完成配置,全程只需要输入数字和回车: **第一步:选择备份频率 [1/3]** ```plain 📅 [1/3] 请选择备份频率: 1) 每隔 N 小时 2) 每天固定时间 3) 每周固定时间 4) 自定义 cron 表达式(高级) 输入 q 退出 请输入选项 [1-4](默认: 2): ``` > 直接按回车使用默认值。大多数人选 **2(每天固定时间)** 就够了。 > **第二步:设置具体时间 [2/3]** 以「每天固定时间」为例: ```plain ⏰ [2/3] 设置执行时间 输入 0 返回上一步 | 输入 q 退出 请输入执行时间,格式 HH:MM(默认: 04:00): 04:00 → 每天 04:00 ``` > 💡 输入 `0` 可以返回上一步重新选择,输入 `q` 退出。 > **第三步:设置保留份数 [3/3]** ```plain 📦 [3/3] 设置保留份数 输入 0 返回上一步 | 输入 q 退出 请输入保留份数(超出自动清理,范围 1-100)(默认: 7): 7 ``` > 保留份数 = 最多保存几个备份文件。超出后自动删除最旧的,防止磁盘被撑满。 > **最终确认** ```plain 📋 备份配置确认: ┌──────────────────────────────────────┐ │ 执行计划: 每天 04:00 │ 保留份数: 7(超出自动清理) │ Cron 表达式: 0 4 * * * └──────────────────────────────────────┘ 确认开启? (Y/n): Y [INFO] ✅ 定时备份已开启! [INFO] 执行计划: 每天 04:00 [INFO] 保留份数: 7 [INFO] 查看状态: bash backup.sh cron-status [INFO] 关闭定时: bash backup.sh cron-off ``` #### 其他频率示例 **每隔 6 小时备份一次**: ```plain ⏰ [2/3] 设置间隔时间 输入 0 返回上一步 | 输入 q 退出 请输入间隔小时数 [1/2/3/4/6/8/12](默认: 6): 6 → 每隔 6 小时(00:00, 06:00, 12:00, 18:00) ``` **每周三和周六凌晨 3:30 备份**: ```plain ⏰ [2/3] 设置执行时间 输入 0 返回上一步 | 输入 q 退出 请选择星期几(可多选,用逗号分隔): 1) 周一 2) 周二 3) 周三 4) 周四 5) 周五 6) 周六 7) 周日 请输入选项(默认: 1,4): 3,6 → 已选择: 周三, 周六 请输入执行时间,格式 HH:MM(默认: 04:00): 03:30 → 每周三、周六 03:30 ``` ### 开启定时备份(快捷方式) 如果你熟悉 cron 表达式,可以直接指定,跳过交互: ```bash cd script # 每天凌晨 4 点备份,保留最近 7 份 bash backup.sh cron-on --cron "0 4 * * *" --keep 7 # 每 12 小时备份一次,保留最近 14 份 bash backup.sh cron-on --cron "0 */12 * * *" --keep 14 # 每周一和周四凌晨 3 点备份,保留最近 10 份 bash backup.sh cron-on --cron "0 3 * * 1,4" --keep 10 ``` ### 查看定时备份状态 ```bash cd script bash backup.sh cron-status ``` **已开启时的输出**: ```plain [INFO] 定时备份状态(版本: s2a3) 状态: ✅ 已开启 执行计划: 每天 04:00 保留份数: 7 Cron 表达式: 0 4 * * * 日志文件: /root/dnf/backup/cron.log [INFO] 最近一次备份: 时间: 2026-05-15 04:00:02 文件: s2a3_20260515_040000.tar.gz (1.2 GB) ``` **未开启时的输出**: ```plain [INFO] 定时备份状态(版本: s2a3) 状态: ❌ 未开启 [INFO] 开启定时备份: bash backup.sh cron-on ``` ### 关闭定时备份 ```bash cd script bash backup.sh cron-off ``` ```plain [INFO] ✅ 定时备份已关闭(版本: s2a3) [INFO] 重新开启: bash backup.sh cron-on ``` > 关闭后不会删除已有的备份文件,只是停止自动创建新备份。 > ### 修改定时备份配置 同一个版本只能有一个定时备份任务。如果需要修改配置(比如改时间或保留份数),需要先关闭再重新开启: ```bash cd script bash backup.sh cron-off # 先关闭 bash backup.sh cron-on # 再重新配置 ``` 如果忘记先关闭,直接执行 `cron-on` 会提示你: ```plain [WARN] ⚠️ 检测到已有定时备份任务(版本: s2a3) 当前配置: 每天 04:00 保留份数: 7 Cron 表达式: 0 4 * * * [INFO] 如需修改,请先关闭再重新开启: bash backup.sh cron-off bash backup.sh cron-on ``` --- ## 常见问题 ### Q: 备份文件有多大? 取决于你的游戏数据量。一般来说,一个备份文件在 **500MB ~ 2GB** 之间。可以用 `bash backup.sh list` 查看每个备份的实际大小。 ### Q: 备份时游戏会中断吗? **会短暂中断。** 为了保证数据一致性,备份时需要先停止容器,打包完成后自动重启。中断时间通常在 **1~5 分钟**,取决于数据量大小和服务器磁盘速度。 > 💡 建议把自动备份时间设在凌晨(如 04:00),这样对玩家影响最小。 > ### Q: 恢复后数据会怎样? 恢复会**完全覆盖**当前的游戏数据,恢复后游戏状态与备份时完全一致。包括:角色等级、装备、金币、仓库物品等全部回到备份时的状态。 > ⚠️ 恢复是不可逆操作,但脚本会在恢复前自动创建一份当前数据的备份(后悔药),万一恢复错了可以再恢复回去。 > ### Q: 备份文件可以在不同服务器之间使用吗? **可以。** 备份文件是标准的 `.tar.gz` 压缩包,可以下载到本地,再上传到另一台服务器的 `backup/` 目录,然后用 `bash backup.sh restore` 恢复。 > ⚠️ 注意:两台服务器的**版本名称**(`vm.cfg` 中的配置)需要一致,否则恢复时会提示版本不匹配(可以选择强制继续)。 > ### Q: 磁盘空间不够怎么办? 1. 用 `bash backup.sh list` 查看备份占用空间 2. 手动删除不需要的旧备份文件(直接在 `backup/` 目录下删除 `.tar.gz` 文件即可) 3. 如果开启了自动备份,可以减小保留份数(先 `cron-off` 再 `cron-on` 重新设置) 4. 定期将备份下载到本地后删除服务器上的备份 ### Q: 备份过程中断电/断网了怎么办? 脚本有中断保护机制: + 如果备份过程中被中断(Ctrl+C 或断电),不完整的备份文件会被自动清理 + 如果备份前停止了容器,中断后容器会被自动重启 + 原有数据不会受到任何影响 ### Q: 自动备份的日志在哪里看? 自动备份的日志保存在 `backup/cron.log` 文件中: ```bash # 查看最近的自动备份日志 tail -50 backup/cron.log ``` ### Q: 定时备份开启后,服务器重启了还会继续吗? **会。** 定时备份是通过系统的 crontab 实现的,服务器重启后 cron 服务会自动恢复,定时任务继续生效。 --- ## 注意事项 1. **备份期间游戏会中断**:建议在玩家较少的时段(如凌晨)进行备份 2. **注意磁盘空间**:每个备份文件可能有 1GB+,请确保磁盘有足够空间。开启自动备份时,合理设置保留份数 3. **建议定期导出**:将备份下载到本地或其他存储,防止服务器故障导致备份也丢失 4. **恢复前请三思**:恢复会覆盖当前所有数据,虽然有自动创建的「后悔药」备份,但仍建议操作前确认清楚 5. **不要手动修改 crontab 中的备份任务**:请通过 `cron-on` / `cron-off` 命令管理,手动修改可能导致状态不一致 6. **备份文件命名规则**:`{版本名称}_{日期}_{时间}.tar.gz`,如 `s2a3_20260515_143000.tar.gz`,请不要手动重命名,否则脚本无法识别 Loading... > 🎯 本工具帮助你在 Linux 服务器上**一键部署** DNF 游戏服务端,全程只需要改一个配置文件、敲几条命令。 > > 即使你不懂 Docker,也能轻松完成。 > --- ## 📖 目录 + [你需要准备什么](#你需要准备什么) + [目录结构一览](#目录结构一览) + [快速开始(4 步完成部署)](#快速开始4-步完成部署) - [第一步:上传并解压](#第一步上传并解压) - [第二步:修改配置文件](#第二步修改配置文件) - [第三步:执行部署脚本](#第三步执行部署脚本) - [第四步:观察启动日志,确认部署成功](#第四步观察启动日志确认部署成功) + [日常运维](#日常运维) - [停止服务](#停止服务) - [启动服务](#启动服务) - [卸载服务](#卸载服务) - [密钥轮换(建议部署后执行)](#密钥轮换建议部署后执行) - [单独查看日志](#单独查看日志) + [配置文件详解](#配置文件详解) + [架构与原理(可选阅读)](#架构与原理可选阅读) - [整体架构图](#整体架构图) - [部署流程图](#部署流程图) - [启动流程图](#启动流程图) - [容器之间的关系](#容器之间的关系) - [数据持久化](#数据持久化) + [常见问题](#常见问题) + [注意事项](#注意事项) --- ## 你需要准备什么 | 条件 | 说明 | | --- | --- | | **一台 Linux 服务器** | CentOS 7/8、Ubuntu 18+ 等主流发行版均可 | | **已安装 Docker** | 容器引擎,用来运行游戏服务 | | **已安装 Docker Compose** | 容器编排工具,用来管理多个容器。Docker 较新版本自带(`docker compose`),旧版需单独安装(`docker-compose`) | | **服务器内存 ≥ 2G** | 推荐 4G 及以上,内存越大越流畅。**如果物理内存不足(如只有 2G),必须开启虚拟内存(swap)**,具体教程请自行搜索「Linux 开启 swap」 | | **镜像文件已就位** | `image/` 目录下需要有 `dnf-mysql-5.6.tar` 和 `dnf-server-s2.tar` 两个镜像文件 | > ⚠️ **前提条件**:服务器上必须已经安装好 **Docker** 和 **Docker Compose**,本文档不负责指导安装。 > > + **云服务器**(如腾讯云、阿里云):在控制台创建实例时,可以直接选择预装 Docker 的系统镜像,开箱即用。 > + **虚拟机 / 物理机**:请自行搜索「CentOS 安装 Docker」或「Ubuntu 安装 Docker」,网上教程很多。 > --- ## 目录结构一览 解压 `server.tar.gz` 后,你会在当前目录得到以下文件结构: ```plain ├── README.md ← 📄 你正在看的这个文档 ├── config/ │ └── vm.cfg ← ⚙️ 【唯一需要你修改的文件】配置文件 ├── image/ │ ├── dnf-mysql-5.6.tar ← 📦 MySQL 数据库镜像 │ └── dnf-server-s2.tar ← 📦 游戏服务端镜像 └── script/ ├── deploy.sh ← 🚀 一键部署脚本(首次使用) ├── start.sh ← ▶️ 启动脚本(日常启动) ├── stop.sh ← ⏹️ 停止脚本(日常停止) ├── remove.sh ← 🗑️ 卸载脚本(删除容器) ├── rotate-key.sh ← 🔑 密钥轮换脚本(建议部署后执行一次) └── init-log.sh ← 📋 日志展示脚本(可单独使用) ``` > 你只需要关注 `config/vm.cfg` 这一个文件,其他的脚本直接运行就好。 > --- ## 快速开始(4 步完成部署) ### 第一步:上传并解压 1. 在服务器上新建一个**空目录**作为工作目录(名字随意,例如 `dnf`): ```bash mkdir -p /root/dnf ``` 2. 将 `server.tar.gz` 上传到这个空目录中。 > 💡 上传方式:可以用 FTP 工具(如 FileZilla、WinSCP)、`scp` 命令、宝塔面板等,选择你熟悉的方式即可。 > 3. 进入该目录并解压: ```bash cd /root/dnf tar -xzvf server.tar.gz ``` 解压后目录里就是 3 个文件夹 + 1 个 README 文档: ```plain /root/dnf/ ├── config/ ├── image/ ├── script/ └── README.md ``` > 后续所有操作都在此目录下进行。 > ### 第二步:修改配置文件 用编辑器打开 `config/vm.cfg`: ```bash vi config/vm.cfg ``` 文件内容如下,**每一项都要根据你的实际情况填写**: ```properties cpu核心数=2 包括虚拟内存的总内存大小(G)=8 game账户密码(8位)=uu5!^%jg root账户密码=88888888 服务访问ip=192.168.200.131 版本名称=s2a3 是否开启dp2和frida插件(true/false)=true 是否开启暴雨登录器网关(true/false)=true 是否开启s2服务端插件(true/false)=true 连接池大小(3-1000)=20 ``` > ⚠️ **重要**:只修改每行 **等号 **`=`** 后面**的值,等号及等号前面的内容是配置项名称,**不要修改**,否则脚本将无法正确解析配置。 > > ⚠️ 各项的含义请看下面的 [配置文件详解](#配置文件详解),**每一项都不能留空**。 > ### 第三步:执行部署脚本 ```bash cd script bash deploy.sh ``` 脚本会自动完成以下所有事情(你只需要等待): 1. ✅ 检查 Docker 和 Docker Compose 是否已安装 2. ✅ 读取你的配置文件 3. ✅ 加载 MySQL 和 Server 的 Docker 镜像 4. ✅ 创建 Docker 网络和数据卷 5. ✅ 生成 docker-compose.yml 编排文件 6. ✅ 启动 MySQL 容器,等待数据库初始化完成 7. ✅ 启动 Server 容器 8. ✅ 自动展示 Server 启动日志 > ⏳ **首次部署**时,MySQL 需要导入大量游戏数据库,可能需要 **5~30 分钟**(取决于服务器性能)。 Server 会自动等待 MySQL 就绪后才启动,不需要你手动干预。 > ### 第四步:观察启动日志,确认部署成功 部署脚本在启动容器后,会**自动展示 Server 的启动日志**,你可以实时看到加载进度: ```plain [INFO] 正在展示启动日志(Ctrl+C 退出)... [12:34:00] - Loading Skills Success [12:34:00] - Loading Items Success [12:34:09] - Loading Quests Success [12:34:09] - Loading Characters Success [12:34:15] GeoIP Allow Country Code : CN [12:34:15] GeoIP Allow Country Code : HK [12:34:15] GeoIP Allow Country Code : KR [12:34:15] GeoIP Allow Country Code : MO [12:34:15] GeoIP Allow Country Code : TW ``` > 看到 **5 个 GeoIP Allow Country Code**(俗称「五国」:CN、HK、KR、MO、TW)就说明**部署成功**了! > > 按 **Ctrl + C** 退出日志查看(不会影响服务运行)。 > --- ## 日常运维 部署完成后,后续的日常操作只需要用以下脚本: | 脚本 | 用途 | | --- | --- | | `start.sh` | 启动服务 | | `stop.sh` | 停止服务 | | `remove.sh` | 卸载容器(保留数据) | | `rotate-key.sh` | 密钥轮换(生成新的 RSA 密钥对,建议部署后执行) | | `init-log.sh` | 单独查看 Server 启动日志 | ### 停止服务 ```bash cd script bash stop.sh ``` 停止顺序:**先停 Server → 再停 MySQL**(脚本自动处理,保证数据安全)。 ### 启动服务 ```bash cd script bash start.sh ``` 启动顺序:**先启动 MySQL → 再启动 Server**(脚本自动处理)。 启动后,脚本会**自动展示游戏服务端的启动日志**,你可以实时看到加载进度: > 💡 如果只想单独查看日志(不启动容器),可以直接执行 `bash init-log.sh`。 > ```plain [INFO] 正在展示启动日志(Ctrl+C 退出)... [12:29:00] - Loading Skills Success [12:29:00] - Loading Items Success [12:29:09] - Loading Quests Success [12:29:09] - Loading Characters Success [12:29:00] GeoIP Allow Country Code : CN [12:29:00] GeoIP Allow Country Code : HK [12:29:00] GeoIP Allow Country Code : KR [12:29:00] GeoIP Allow Country Code : MO [12:29:00] GeoIP Allow Country Code : TW ``` > 看到 **5 个 GeoIP Allow Country Code**(俗称「五国」)就说明启动成功了! > > 按 **Ctrl + C** 退出日志查看(不会影响服务运行)。 > ### 卸载服务 ```bash cd script bash remove.sh ``` 卸载会**停止并删除容器**,但**保留数据卷**(游戏数据不丢失)。如需重新部署,再次执行 `deploy.sh` 即可。 如果要**彻底清除所有数据**(不可恢复),加 `--volumes` 参数: ```bash bash remove.sh --volumes ``` ### 密钥轮换(建议部署后执行) ```bash cd script bash rotate-key.sh ``` 生成新的 RSA 2048 密钥对,覆盖 server-data 数据卷中的密钥文件。执行后需要 `bash stop.sh` + `bash start.sh` 重启服务才能生效。 > ⚠️ **安全提示**:镜像中自带的默认密钥是所有人共用的,不替换也能正常运行,但存在安全风险(其他人可以用相同密钥伪造登录)。建议部署后执行一次密钥轮换。 > ### 单独查看日志 ```bash cd script bash init-log.sh ``` 直接展示 Server 当前的启动日志,适用于想确认服务状态但不想重启的场景。 --- ## 配置文件详解 配置文件路径:`config/vm.cfg` | 配置项 | 示例值 | 说明 | | --- | --- | --- | | `cpu核心数` | `2` | 你的服务器有几个 CPU 核心。不知道的话,在服务器上执行 `nproc` 查看 | | `包括虚拟内存的总内存大小(G)` | `8` | 服务器的总内存(单位:GB)。不知道的话,执行 `free -g` 查看 `total` 列。**包含虚拟内存(swap)** | | `game账户密码(8位)` | `uu5!^%jg` | 游戏数据库的 game 账户密码,**必须恰好 8 位**,否则游戏无法连接数据库 | | `root账户密码` | `88888888` | MySQL 数据库的 root 管理员密码,可以自定义 | | `服务访问ip` | `192.168.200.131` | 玩家连接游戏时使用的 IP 地址。如果是公网服务器,填公网 IP;如果是内网/局域网,填内网 IP | | `版本名称` | `s2a3` | 给这套部署起个名字。所有容器、数据卷都会以此为前缀(如 `s2a3-server`、`s2a3-mysql`)。如果你想在同一台服务器上部署多套,改成不同的名字即可(如 `s3a3`) | | `是否开启dp2和frida插件(true/false)` | `true` | DP2 插件开关。开启后支持 Lua/JS 脚本扩展游戏功能 | | `是否开启暴雨登录器网关(true/false)` | `true` | 暴雨登录器网关开关。开启后支持暴雨登录器连接 | | `是否开启s2服务端插件(true/false)` | `true` | 70s2 引擎与分辨率适配插件开关 | | `连接池大小(3-1000)` | `20` | TCP 连接池大小,取代 df_channel_r/df_bridge_r 硬编码的 1000 槽,可显著节省内存。单人玩填 3,小型服务器 10–20,中等部署 256,填 1000 等于禁用补丁 | > ⚠️ **关于内存配置**:`包括虚拟内存的总内存大小(G)` 填写的是你**打算分配给游戏服务端的总内存**(物理内存 + swap 虚拟内存)。如果填写的值大于实际可用内存,会导致 Server 容器启动失败(OOM)。例如物理内存 2G + swap 6G = 可填 8。 > > 💡 **关于版本名称**:这个名字决定了容器和数据卷的命名前缀。比如设置为 `s2a3`,那么: > > + MySQL 容器名 → `s2a3-mysql` > + Server 容器名 → `s2a3-server` > + 数据卷 → `s2a3-mysql-data`、`s2a3-server-log` 等 > > 你可以在同一台服务器上部署多个版本(如 `s2a3` 和 `s3a3`),它们互不干扰。 > --- ## 架构与原理(可选阅读) > 以下内容帮助你理解"脚本背后做了什么",**不看也不影响使用**。 > ### 整体架构图 ```plain ┌─────────────────────────────────────────────────────────┐ │ Linux 服务器 │ │ │ │ ┌─────────────────┐ ┌─────────────────────────┐ │ │ │ s2a3-mysql │ │ s2a3-server │ │ │ │ (MySQL 5.6) │◄──────│ (DNF 游戏服务端) │ │ │ │ │ 3306 │ │ │ │ │ 存储游戏数据 │ │ 运行游戏逻辑 │ │ │ └────────┬─────────┘ └────────┬────────────────┘ │ │ │ │ │ │ ┌─────▼─────┐ ┌───────▼──────────┐ │ │ │ mysql-data │ │ server-data │ │ │ │ mysql-conf │ │ server-log │ │ │ └───────────┘ └──────────────────┘ │ │ (数据卷:持久化存储,容器删了数据还在) │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ Docker 网络: dnf (172.20.0.0/16) │ │ │ │ 两个容器通过此网络互相通信 │ │ │ └─────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ │ 玩家通过 IP 连接 ``` ### 部署流程图 以下是从拿到压缩包到部署完成的完整流程: ```mermaid flowchart TD A0["新建空目录并上传 server.tar.gz"] --> A1["tar -xzvf server.tar.gz"] A1 --> A2["cd script"] A2 --> A["bash deploy.sh"] A --> B{"检查 Docker 环境"} B -- "Docker ✅ / Compose ✅" --> C["读取 config/vm.cfg"] B -- "有缺失 ❌" --> B1["报错退出,提示安装"] C --> D{"配置项是否完整?"} D -- "是" --> E["加载 Docker 镜像<br/>dnf-mysql-5.6.tar<br/>dnf-server-s2.tar"] D -- "否" --> D1["报错退出,提示缺少哪项"] E --> F["创建 Docker 网络 dnf"] F --> G["创建 4 个数据卷<br/>mysql-data / mysql-conf<br/>server-data / server-log"] G --> H["根据配置生成<br/>docker-compose.yml"] H --> I["启动 MySQL 容器"] I --> J["MySQL 健康检查<br/>(等待初始化完成)"] J --> K["启动 Server 容器"] K --> L["展示 Server 启动日志"] L --> M["看到五国 → ✅ 部署成功!<br/>Ctrl+C 退出日志"] ``` ### 启动流程图 以下是执行 `start.sh` 时的流程: ```mermaid flowchart TD A["bash start.sh"] --> B["启动 MySQL 容器"] B --> C["启动 Server 容器"] C --> D["等待 Server 产生新日志"] D --> E["tail -f 展示启动日志"] E --> F["用户看到日志后<br/>按 Ctrl+C 退出"] ``` ### 容器之间的关系 ```mermaid flowchart LR subgraph MySQL容器 DB["MySQL 5.6<br/>端口 3306<br/>存储 21 个游戏数据库"] end subgraph Server容器 SRV["DNF 游戏服务端<br/>16 个子服务进程<br/>+ 网关 + 监控"] end SRV -- "读写游戏数据<br/>(通过 Docker 网络)" --> DB SRV -- "对外暴露端口<br/>20303 等" --> 玩家客户端 ``` **两个容器的分工**: | 容器 | 角色 | 类比 | | --- | --- | --- | | **MySQL 容器** | 数据库,存储所有游戏数据(角色、装备、账号等) | 相当于"仓库" | | **Server 容器** | 游戏服务端,运行游戏逻辑,处理玩家请求 | 相当于"工厂" | Server 依赖 MySQL,所以: + **启动时**:先启动 MySQL → 再启动 Server + **停止时**:先停止 Server → 再停止 MySQL ### 数据持久化 部署时会创建 4 个 **Docker 数据卷**,用来持久化存储数据。即使容器被删除重建,数据也不会丢失: | 数据卷 | 用途 | 说明 | | --- | --- | --- | | `{版本名称}-mysql-data` | MySQL 数据文件 | 所有游戏数据库的实际数据 | | `{版本名称}-mysql-conf` | MySQL 配置文件 | 数据库的自定义配置 | | `{版本名称}-server-data` | Server 数据文件 | 游戏脚本(pvf)、主程序、密钥、插件配置等(详见下方) | | `{版本名称}-server-log` | Server 日志文件 | 游戏运行日志,`start.sh` 展示的就是这里的日志 | > 💡 **简单理解**:数据卷就像一个"保险箱",容器是"工人"。工人可以换,但保险箱里的东西一直在。 > #### server-data 数据卷详细内容 `{版本名称}-server-data` 卷挂载到容器内的 `/data` 目录,包含以下可热更文件(修改后重启容器即生效): | 文件/目录 | 作用 | 修改场景 | | --- | --- | --- | | `Script.pvf` | 游戏脚本主文件(约 90MB) | 自定义游戏内容(技能、装备、地图等) | | `df_game_r` | 游戏服主程序(约 35MB) | 切换不同版本的服务端二进制 | | `publickey.pem` | 网关公钥 | 密钥轮换 | | `privatekey.pem` | 网关私钥 | 密钥轮换 | | `dp2/df_game_r.lua` | DP2 Lua 主脚本 | 编写/调试 DP2 插件功能 | | `dp2/df_game_r.js` | DP2 JS 脚本 | 编写/调试 DP2 插件功能 | | `dp2/frida_config.json` | DP2 Frida 配置 | 调整 DP2 插件配置 | | `config.ini` | 暴雨登录器网关配置 | 一般无需手动修改。容器启动时会自动从环境变量获取数据库地址、端口、账号、密码等配置 | | `so.cfg` | s2 插件 monitor 时间触发参数 | 调整攻城战/活动时间 | | `iteminfo.dat`(可选) | 拍卖行/点券物品信息 | 修复拍卖行搜索功能 | > 💡 **热更方式**:直接在宿主机上编辑数据卷中的文件,然后 `bash stop.sh` + `bash start.sh` 重启即可生效。 数据卷路径可通过 `docker volume inspect {版本名称}-server-data --format '{{.Mountpoint}}'` 查看。 > --- ## 常见问题 ### Q: 部署时卡在 MySQL 初始化很久,正常吗? **正常。** 首次部署时,MySQL 需要创建 21 个游戏数据库并导入大量 SQL 数据,根据服务器性能不同,可能需要 5~30 分钟。脚本设置了最长 30 分钟的等待时间,Server 会在 MySQL 完全就绪后才自动启动。 你可以在另一个终端窗口查看 MySQL 的实时日志: ```bash docker logs -f s2a3-mysql ``` ### Q: deploy.sh 报错"未检测到 Docker"怎么办? 说明你的服务器还没有安装 Docker 或 Docker Compose。云服务器(如腾讯云、阿里云)可以在控制台选择预装 Docker 的系统镜像;虚拟机请自行搜索安装教程。安装完成后重新执行 `deploy.sh`。 ### Q: 可以在同一台服务器上部署多套吗? **可以共存,但不能同时运行。** 修改 `vm.cfg` 中的 `版本名称` 为不同的值(如 `s2a3` 和 `s3a3`),然后分别执行 `deploy.sh`,每套部署的容器和数据卷都以版本名称为前缀,互不干扰。 但由于多个版本使用相同的端口(如 3306、20303),**同一时间只能运行一个版本**。想玩哪个版本,就先停掉当前运行的版本,再启动目标版本即可: ```bash # 停掉当前版本(假设正在运行 s2a3) bash stop.sh # 修改 vm.cfg 中的版本名称为 s3a3,然后启动 bash start.sh ``` ### Q: 停止后再启动,数据会丢失吗? **不会。** 所有游戏数据都保存在 Docker 数据卷中,停止/启动容器不会影响数据。 ### Q: start.sh 启动后日志一直在等待怎么办? 如果超过 120 秒仍未看到日志,可能是 Server 容器启动异常。请检查: ```bash # 查看 Server 容器状态 docker ps -a | grep server # 查看 Server 容器日志 docker logs s2a3-server ``` ### Q: 首次部署后进游戏连不上 / 没有频道怎么办? 首次执行 `deploy.sh` 时,Server 容器可能会出现 **core dump** 导致启动不完全成功(表现为游戏进去连不上服务器或者看不到频道)。这是正常现象,**直接停止再启动一次即可**: ```bash bash stop.sh bash start.sh ``` 看到「五国」日志输出后再进游戏,一般就正常了。 ### Q: game 账户密码可以随便设吗? **必须恰好 8 位字符**,这是游戏服务端的硬性限制。少于或多于 8 位都会导致游戏无法连接数据库。密码可以包含字母、数字和特殊字符。 --- ## 注意事项 1. **建议部署后轮换密钥**:执行 `bash rotate-key.sh` 生成你自己的密钥对,然后 `stop.sh` + `start.sh` 重启。镜像默认密钥所有人相同,不替换也能运行但存在安全风险 2. **首次部署请耐心等待**:MySQL 初始化需要时间,不要中途强制关闭终端或 Ctrl+C 中断 3. **不要手动修改 **`script/docker-compose.yml`:这个文件由 `deploy.sh` 自动生成,每次部署都会覆盖。如需调整参数,请修改 `config/vm.cfg` 后重新执行 `deploy.sh` 4. **game 密码必须 8 位**:这是硬性要求,不是建议 5. **服务访问 IP 要填对**:如果是云服务器,填公网 IP;如果是局域网,填局域网 IP。填错了玩家将无法连接 6. **停止和启动有顺序**:请使用 `stop.sh` 和 `start.sh` 脚本操作,不要直接用 `docker stop/start` 命令,脚本会保证正确的启停顺序 7. **重新部署会停止旧容器**:执行 `deploy.sh` 会先停止并删除同名的旧容器,然后创建新容器。数据卷中的数据不受影响 8. **镜像文件不要删**:`image/` 目录下的 `.tar` 文件是 Docker 镜像的离线包,首次部署时需要加载。加载完成后可以删除以节省磁盘空间,但建议保留备用 > 🎯 本工具帮助你**一键备份**和**恢复**游戏数据,支持手动备份、定时自动备份,操作简单,对小白友好。 > > 备份文件就是标准的 `.tar.gz` 压缩包,可以直接下载到本地保存。 > --- ## 📖 目录 + [备份了什么?](#备份了什么) + [命令一览](#命令一览) + [创建备份](#创建备份) + [查看备份列表](#查看备份列表) + [恢复备份](#恢复备份) + [导出备份到本地](#导出备份到本地) + [自动定时备份](#自动定时备份) - [开启定时备份(交互式)](#开启定时备份交互式) - [开启定时备份(快捷方式)](#开启定时备份快捷方式) - [查看定时备份状态](#查看定时备份状态) - [关闭定时备份](#关闭定时备份) - [修改定时备份配置](#修改定时备份配置) + [常见问题](#常见问题) + [注意事项](#注意事项) --- ## 备份了什么? 备份包含游戏的**全部核心数据**,恢复后游戏状态与备份时完全一致: | 数据卷 | 内容 | 包含什么 | | --- | --- | --- | | `{版本名称}-mysql-data` | MySQL 数据库 | 角色、装备、账号、仓库、拍卖行等所有游戏数据 | | `{版本名称}-server-data` | 服务端数据 | 游戏脚本(pvf)、主程序、密钥、插件配置等 | > 💡 备份文件是标准的 `.tar.gz` 压缩包,存放在 `backup/` 目录下,可以直接用 scp、FTP 等工具下载到本地保存。 > --- ## 命令一览 所有命令都在 `script/` 目录下执行: ```bash cd script bash backup.sh create # 创建备份 bash backup.sh list # 查看备份列表 bash backup.sh restore # 恢复备份(交互式选择) bash backup.sh cron-on # 开启自动定时备份 bash backup.sh cron-off # 关闭自动定时备份 bash backup.sh cron-status # 查看定时备份状态 bash backup.sh # 显示帮助信息 ``` --- ## 创建备份 ```bash cd script bash backup.sh create ``` 脚本会自动完成以下事情: 1. ⏹ 停止游戏容器(保证数据一致性) 2. 📦 打包两个数据卷为 `.tar.gz` 压缩包 3. ▶️ 重新启动游戏容器 4. ✅ 显示备份文件路径和大小 **输出示例**: ```plain [INFO] 开始创建备份(版本: s2a3)... [INFO] ⏹ 停止容器以确保数据一致性(游戏将短暂中断,备份完成后自动重启)... [INFO] 正在打包备份数据(数据量较大时可能需要几分钟,请耐心等待)... [INFO] MySQL 数据: /var/lib/docker/volumes/s2a3-mysql-data/_data [INFO] Server 数据: /var/lib/docker/volumes/s2a3-server-data/_data [INFO] ▶ 重新启动容器... [INFO] ✅ 备份完成! [INFO] 文件: /root/dnf/backup/s2a3_20260515_143000.tar.gz [INFO] 大小: 1.2 GB ``` > ⚠️ **备份期间游戏会短暂中断**(通常 1~5 分钟),备份完成后会自动重启。如果容器本来就是停止的,备份后不会自动启动。 > --- ## 查看备份列表 ```bash cd script bash backup.sh list ``` **输出示例**: ```plain [INFO] 备份列表(版本: s2a3) 序号 备份时间 文件大小 文件名 ────────────────────────────────────────────────────────────── 1 2026-05-15 14:30:00 1.2 GB s2a3_20260515_143000.tar.gz 2 2026-05-14 04:00:00 1.1 GB s2a3_20260514_040000.tar.gz 3 2026-05-13 04:00:00 1.1 GB s2a3_20260513_040000.tar.gz [INFO] 共 3 个备份,总占用 3.4 GB [INFO] 备份目录: /root/dnf/backup/ ``` > 列表按时间倒序排列,最新的备份在最前面。只显示当前版本的备份文件。 > --- ## 恢复备份 ### 方式一:交互式选择(推荐) ```bash cd script bash backup.sh restore ``` 脚本会先列出所有备份,你输入序号即可选择要恢复的备份: ```plain [INFO] 备份列表(版本: s2a3) 序号 备份时间 文件大小 文件名 ────────────────────────────────────────────────────────────── 1 2026-05-15 14:30:00 1.2 GB s2a3_20260515_143000.tar.gz 2 2026-05-14 04:00:00 1.1 GB s2a3_20260514_040000.tar.gz 请输入要恢复的备份序号: 1 ⚠️ 恢复将覆盖当前所有数据!此操作不可逆! ⚠️ 恢复后游戏状态将回到备份时的状态(角色、装备、金币等全部回档) 确认恢复? (y/N): y [INFO] 正在创建恢复前备份(后悔药,数据量较大时可能需要几分钟)... [INFO] ✅ 恢复前备份已创建: s2a3_20260515_150000_pre-restore.tar.gz (1.2 GB) [INFO] ⏹ 停止容器... [INFO] 正在恢复数据(数据量较大时可能需要几分钟,请耐心等待)... [INFO] 恢复 MySQL 数据... [INFO] 恢复 Server 数据... [INFO] ▶ 启动容器... [INFO] ✅ 恢复完成! [INFO] 已恢复备份: s2a3_20260515_143000.tar.gz [INFO] 恢复前备份: s2a3_20260515_150000_pre-restore.tar.gz ``` ### 方式二:指定文件名恢复 ```bash cd script bash backup.sh restore s2a3_20260515_143000.tar.gz ``` > 💡 **后悔药**:恢复前会自动创建一份当前数据的备份(文件名带 `_pre-restore` 标记)。万一恢复后发现不对,可以用这份备份再恢复回去。 > --- ## 导出备份到本地 备份文件就是普通的 `.tar.gz` 压缩包,直接下载即可: ```bash # 在你的本地电脑上执行(不是服务器上) scp root@你的服务器IP:/root/dnf/backup/s2a3_20260515_143000.tar.gz ./ ``` 也可以用 FTP 工具(FileZilla、WinSCP 等)连接服务器,进入 `backup/` 目录下载。 > 💡 建议定期将备份下载到本地或其他存储,防止服务器硬盘故障导致备份也丢失。 > --- ## 自动定时备份 ### 开启定时备份(交互式) ```bash cd script bash backup.sh cron-on ``` 脚本会一步步引导你完成配置,全程只需要输入数字和回车: **第一步:选择备份频率 [1/3]** ```plain 📅 [1/3] 请选择备份频率: 1) 每隔 N 小时 2) 每天固定时间 3) 每周固定时间 4) 自定义 cron 表达式(高级) 输入 q 退出 请输入选项 [1-4](默认: 2): ``` > 直接按回车使用默认值。大多数人选 **2(每天固定时间)** 就够了。 > **第二步:设置具体时间 [2/3]** 以「每天固定时间」为例: ```plain ⏰ [2/3] 设置执行时间 输入 0 返回上一步 | 输入 q 退出 请输入执行时间,格式 HH:MM(默认: 04:00): 04:00 → 每天 04:00 ``` > 💡 输入 `0` 可以返回上一步重新选择,输入 `q` 退出。 > **第三步:设置保留份数 [3/3]** ```plain 📦 [3/3] 设置保留份数 输入 0 返回上一步 | 输入 q 退出 请输入保留份数(超出自动清理,范围 1-100)(默认: 7): 7 ``` > 保留份数 = 最多保存几个备份文件。超出后自动删除最旧的,防止磁盘被撑满。 > **最终确认** ```plain 📋 备份配置确认: ┌──────────────────────────────────────┐ │ 执行计划: 每天 04:00 │ 保留份数: 7(超出自动清理) │ Cron 表达式: 0 4 * * * └──────────────────────────────────────┘ 确认开启? (Y/n): Y [INFO] ✅ 定时备份已开启! [INFO] 执行计划: 每天 04:00 [INFO] 保留份数: 7 [INFO] 查看状态: bash backup.sh cron-status [INFO] 关闭定时: bash backup.sh cron-off ``` #### 其他频率示例 **每隔 6 小时备份一次**: ```plain ⏰ [2/3] 设置间隔时间 输入 0 返回上一步 | 输入 q 退出 请输入间隔小时数 [1/2/3/4/6/8/12](默认: 6): 6 → 每隔 6 小时(00:00, 06:00, 12:00, 18:00) ``` **每周三和周六凌晨 3:30 备份**: ```plain ⏰ [2/3] 设置执行时间 输入 0 返回上一步 | 输入 q 退出 请选择星期几(可多选,用逗号分隔): 1) 周一 2) 周二 3) 周三 4) 周四 5) 周五 6) 周六 7) 周日 请输入选项(默认: 1,4): 3,6 → 已选择: 周三, 周六 请输入执行时间,格式 HH:MM(默认: 04:00): 03:30 → 每周三、周六 03:30 ``` ### 开启定时备份(快捷方式) 如果你熟悉 cron 表达式,可以直接指定,跳过交互: ```bash cd script # 每天凌晨 4 点备份,保留最近 7 份 bash backup.sh cron-on --cron "0 4 * * *" --keep 7 # 每 12 小时备份一次,保留最近 14 份 bash backup.sh cron-on --cron "0 */12 * * *" --keep 14 # 每周一和周四凌晨 3 点备份,保留最近 10 份 bash backup.sh cron-on --cron "0 3 * * 1,4" --keep 10 ``` ### 查看定时备份状态 ```bash cd script bash backup.sh cron-status ``` **已开启时的输出**: ```plain [INFO] 定时备份状态(版本: s2a3) 状态: ✅ 已开启 执行计划: 每天 04:00 保留份数: 7 Cron 表达式: 0 4 * * * 日志文件: /root/dnf/backup/cron.log [INFO] 最近一次备份: 时间: 2026-05-15 04:00:02 文件: s2a3_20260515_040000.tar.gz (1.2 GB) ``` **未开启时的输出**: ```plain [INFO] 定时备份状态(版本: s2a3) 状态: ❌ 未开启 [INFO] 开启定时备份: bash backup.sh cron-on ``` ### 关闭定时备份 ```bash cd script bash backup.sh cron-off ``` ```plain [INFO] ✅ 定时备份已关闭(版本: s2a3) [INFO] 重新开启: bash backup.sh cron-on ``` > 关闭后不会删除已有的备份文件,只是停止自动创建新备份。 > ### 修改定时备份配置 同一个版本只能有一个定时备份任务。如果需要修改配置(比如改时间或保留份数),需要先关闭再重新开启: ```bash cd script bash backup.sh cron-off # 先关闭 bash backup.sh cron-on # 再重新配置 ``` 如果忘记先关闭,直接执行 `cron-on` 会提示你: ```plain [WARN] ⚠️ 检测到已有定时备份任务(版本: s2a3) 当前配置: 每天 04:00 保留份数: 7 Cron 表达式: 0 4 * * * [INFO] 如需修改,请先关闭再重新开启: bash backup.sh cron-off bash backup.sh cron-on ``` --- ## 常见问题 ### Q: 备份文件有多大? 取决于你的游戏数据量。一般来说,一个备份文件在 **500MB ~ 2GB** 之间。可以用 `bash backup.sh list` 查看每个备份的实际大小。 ### Q: 备份时游戏会中断吗? **会短暂中断。** 为了保证数据一致性,备份时需要先停止容器,打包完成后自动重启。中断时间通常在 **1~5 分钟**,取决于数据量大小和服务器磁盘速度。 > 💡 建议把自动备份时间设在凌晨(如 04:00),这样对玩家影响最小。 > ### Q: 恢复后数据会怎样? 恢复会**完全覆盖**当前的游戏数据,恢复后游戏状态与备份时完全一致。包括:角色等级、装备、金币、仓库物品等全部回到备份时的状态。 > ⚠️ 恢复是不可逆操作,但脚本会在恢复前自动创建一份当前数据的备份(后悔药),万一恢复错了可以再恢复回去。 > ### Q: 备份文件可以在不同服务器之间使用吗? **可以。** 备份文件是标准的 `.tar.gz` 压缩包,可以下载到本地,再上传到另一台服务器的 `backup/` 目录,然后用 `bash backup.sh restore` 恢复。 > ⚠️ 注意:两台服务器的**版本名称**(`vm.cfg` 中的配置)需要一致,否则恢复时会提示版本不匹配(可以选择强制继续)。 > ### Q: 磁盘空间不够怎么办? 1. 用 `bash backup.sh list` 查看备份占用空间 2. 手动删除不需要的旧备份文件(直接在 `backup/` 目录下删除 `.tar.gz` 文件即可) 3. 如果开启了自动备份,可以减小保留份数(先 `cron-off` 再 `cron-on` 重新设置) 4. 定期将备份下载到本地后删除服务器上的备份 ### Q: 备份过程中断电/断网了怎么办? 脚本有中断保护机制: + 如果备份过程中被中断(Ctrl+C 或断电),不完整的备份文件会被自动清理 + 如果备份前停止了容器,中断后容器会被自动重启 + 原有数据不会受到任何影响 ### Q: 自动备份的日志在哪里看? 自动备份的日志保存在 `backup/cron.log` 文件中: ```bash # 查看最近的自动备份日志 tail -50 backup/cron.log ``` ### Q: 定时备份开启后,服务器重启了还会继续吗? **会。** 定时备份是通过系统的 crontab 实现的,服务器重启后 cron 服务会自动恢复,定时任务继续生效。 --- ## 注意事项 1. **备份期间游戏会中断**:建议在玩家较少的时段(如凌晨)进行备份 2. **注意磁盘空间**:每个备份文件可能有 1GB+,请确保磁盘有足够空间。开启自动备份时,合理设置保留份数 3. **建议定期导出**:将备份下载到本地或其他存储,防止服务器故障导致备份也丢失 4. **恢复前请三思**:恢复会覆盖当前所有数据,虽然有自动创建的「后悔药」备份,但仍建议操作前确认清楚 5. **不要手动修改 crontab 中的备份任务**:请通过 `cron-on` / `cron-off` 命令管理,手动修改可能导致状态不一致 6. **备份文件命名规则**:`{版本名称}_{日期}_{时间}.tar.gz`,如 `s2a3_20260515_143000.tar.gz`,请不要手动重命名,否则脚本无法识别 最后修改:2026 年 05 月 17 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏
1 条评论
评论测试