服务器迁移实战:从环境盘点到数据校验与业务切换
服务器迁移不仅是复制网站目录。数据库、运行库、服务启动配置、定时任务、证书以及外部访问地址,都可能影响迁移后的业务。
本文以 Linux、Nginx、PHP、MySQL 和 Supervisor 部署的业务为例,介绍允许停机时的一套迁移流程。Docker、跨系统或跨架构迁移需要调整具体方法。
本文所有 IP、域名、用户名和路径均为示例,不对应真实部署。
192.0.2.10、198.51.100.20是文档示例 IP,example.com是示例域名,不能直接用于真实连接。不要在公开文章中放入真实凭据、内网拓扑、数据库配置或完整系统备份。
一、先明确迁移边界
开始前,至少确认:
- 旧、新服务器的系统版本、CPU 架构、磁盘空间与内存。
- 需要迁移的应用、数据库、上传文件和后台服务。
- 是否允许停机,以及新服务器是否存在需要保留的数据。
- 域名、CDN、对象存储、邮件服务和第三方 IP 白名单。
- SSH 登录方式、操作权限和回退要求。
“迁移全部业务”不等于把旧系统根目录覆盖到新系统。新服务器的网络、SSH、磁盘挂载、主机身份和云厂商代理通常应保留自身配置。
本文采用“停机备份 → 传输恢复 → 核对数据 → 验证业务 → 切换入口”的流程。低停机迁移则需要数据库复制、增量同步和更严格的写入切换设计。
二、配置专用 SSH 密钥
在自己的管理电脑上生成专用密钥,按提示设置私钥口令:
ssh-keygen -t ed25519 -f ~/.ssh/migration_ed25519 -C migration-example通过服务器控制台或现有可信连接,把 .pub 公钥的一整行加入两台服务器对应用户的 ~/.ssh/authorized_keys。不要把私钥上传到服务器。
目标用户的 SSH 目录权限应为:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys测试登录:
ssh -i ~/.ssh/migration_ed25519 deploy@192.0.2.10
ssh -i ~/.ssh/migration_ed25519 deploy@198.51.100.20首次连接时,通过云控制台等可信渠道核对 SSH 主机指纹。不要为了省事全局关闭主机密钥检查。下文涉及系统目录的命令,应使用 sudo 或经过授权的管理员会话执行。
三、只读盘点旧服务器
先看系统、资源和服务:
cat /etc/os-release
uname -m
df -hT
free -h
lsblk
systemctl list-units --type=service --state=running --no-pager
ss -lntup
crontab -l再看软件版本:
nginx -v
php -v
mysql --version
command -v docker
command -v supervisorctl不能只看当前正在运行的服务,还要检查:
- systemd 和旧式 init 启动脚本。
- Supervisor 配置及其托管程序。
/etc/cron.d、各业务用户的 crontab 和 systemd timers。- 网站根目录、附件目录、软链接目标和外部挂载。
- MySQL 实际数据目录及配置文件。
- Nginx 虚拟主机、重写规则、证书和反向代理目标。
- FTP 账户数据库、TLS 证书及被动端口设置。
- 应用配置中的硬编码地址、数据库账号和外部依赖。
宝塔环境的软件可能位于 /www/server,网站可能位于 /www/wwwroot;其他环境应以实际配置为准。不要把包含密码的配置输出到公开日志或博客。
最终整理出一份私有迁移清单,写清每个服务的文件、配置、依赖、启动方式和验收方式。
四、选择迁移方法
| 场景 | 通常采用的方法 |
|---|---|
| 同系统、同架构、相同软件版本 | 选择性复制应用环境,验证动态依赖 |
| 系统、架构或数据库版本不同 | 在新服务器安装目标环境,通过受支持的导出导入迁移 |
| Docker Compose | 迁移 Compose、配置和持久化数据,单独设计数据库一致性备份 |
| 数据量大、停机要求短 | 预同步文件、数据库复制或增量备份,最终暂停写入后切换 |
即使系统名称相同,动态库版本和软件编译参数也可能不同。复制可执行文件后,需要检查依赖并执行实际功能测试。
MySQL 数据目录不能随意跨版本复制。使用物理备份前,要核对数据库版本、存储引擎、加密密钥、目录布局及恢复方式;不确定时优先选择兼容的逻辑导出导入。
五、停止所有写入,再制作一致性备份
先备份新服务器自己的配置,并在云平台创建合适的恢复点。快照能否保证数据库一致性取决于创建方式,不能替代数据库一致性设计。
按应用依赖顺序停止旧服务器的写入来源,例如网站入口、任务队列和定时任务,然后停止数据库。以下服务名是示例,不能直接照搬:
sudo systemctl stop example-worker.service
sudo systemctl stop example-scheduler.service
sudo systemctl stop nginx.service
sudo systemctl stop php-fpm.service
sudo systemctl stop mysqld.service停止前要先记录哪些服务原本在运行。停止后应检查进程和连接,不能仅凭停止命令没有报错,就认为没有写入。还需要排除远程数据库客户端、事件调度器和其他后台程序。
方案 A:逻辑导出数据库
逻辑导出需要数据库保持运行。应先停止应用写入,再导出,最后按迁移方案决定是否停止数据库:
mysqldump -u backup -p \
--single-transaction --routines --events --triggers \
--databases example_db > example_db.sql--single-transaction 主要用于事务表的一致性视图,不会自动保证非事务表或并发 DDL 的一致性。导出账户权限、字符集和跨版本兼容性也需要检查。账号与授权通常应单独处理,不能假定只导出业务库就迁移了全部用户。
方案 B:数据库完全停止后复制数据目录
只在已确认版本和物理恢复方式兼容时采用。必须确认数据库进程已退出,复制实际数据目录以及恢复需要的配置和密钥。不要直接打包正在运行的数据库数据文件。
备份应用与配置
先创建仅管理员可访问的目录,再按盘点清单打包:
BACKUP_DIR=/var/backups/migration-example
sudo install -d -m 700 "$BACKUP_DIR"
sudo tar --acls --xattrs -czpf "$BACKUP_DIR/app.tar.gz" \
-C /srv example-app
sudo tar --acls --xattrs -czpf "$BACKUP_DIR/nginx-config.tar.gz" \
-C /etc nginx单独备份数据库、证书、Supervisor、服务单元、定时任务及需要的用户文件。保留原文件所有者、权限、ACL 和扩展属性,并记录恢复要求。
不要无差别打包整个 /usr/local 或覆盖整个 /etc。其中可能包含云安全代理、机器身份、网络配置和不可迁移的运行状态。软件依赖应按清单安装或选择性迁移;云厂商代理通常由新实例自己维护。
记录软件包清单,便于补齐依赖:
# RPM 系统
rpm -qa > packages.txt
# Debian 系统
dpkg-query -W > packages.txt软件包清单是盘点资料,不是可以无条件批量安装的脚本。
六、传输备份并校验
先在旧服务器生成哈希:
cd /var/backups/migration-example
sha256sum app.tar.gz nginx-config.tar.gz > SHA256SUMS使用已核验主机身份的 SSH 连接传输文件。两端都可从管理电脑访问时,可以通过管理电脑中转,也可以在已配置安全认证的前提下使用 scp 或 rsync。
备份传输必须加密,目标目录也应限制访问。不要为了速度把备份放到公开下载目录。
在新服务器同一备份目录中验证:
sha256sum -c SHA256SUMS同一云网络内传输通常能减少公网传输开销,但必须先确认网络互通、SSH 主机身份和访问控制。如果使用临时传输密钥,要限制来源与用途,并在完成后撤销目标端授权、删除临时私钥。
不要把管理电脑长期使用的私钥复制到旧服务器上。
七、在新服务器恢复
先安装兼容的软件和依赖,创建相应业务用户。恢复文件所有权时,核对旧、新服务器的 UID/GID,不能仅凭用户名相同就认定权限正确。
先查看归档内容,再解压到暂存目录:
sudo tar -tzf /var/backups/migration-example/app.tar.gz
sudo install -d -m 700 /var/backups/migration-example/staging
sudo tar --acls --xattrs -xzpf \
/var/backups/migration-example/app.tar.gz \
-C /var/backups/migration-example/staging检查内容和路径后,再安装到预定业务目录。配置文件应与新服务器合并,避免覆盖网络、SSH、磁盘挂载和机器身份。
数据库恢复有两条对应路径:
- 逻辑备份:启动兼容数据库,导入业务库并恢复必要授权,保持应用和任务关闭直至核对完成。
- 停库物理备份:保持目标数据库停止,按数据库支持的物理恢复流程恢复,核对目录权限和配置后再启动。
逻辑备份导入示例:
mysql -u admin -p < example_db.sql复制编译好的程序后,检查依赖:
ldd /path/to/trusted/application只对可信程序使用 ldd。如果出现 not found,应优先从可信软件源安装依赖。不要直接覆盖新系统的 glibc、动态加载器等核心组件。
同时检查 SELinux 上下文、目录访问权限和应用可写目录,不要用全目录 chmod 777 或关闭 SELinux 来掩盖问题。
八、修改与服务器地址有关的配置
需要检查的常见位置包括:
- 前端 API 地址和 WebSocket 地址。
- 后端监听地址、回调地址和数据库连接。
- Nginx 的
server_name、反向代理和重定向。 - FTP 对外地址、第三方 IP 白名单。
- 客户端保存的服务器地址。
- DNS、CDN、负载均衡和对象存储跨域配置。
搜索时优先使用固定字符串,避免 IP 中的点被当成正则通配符:
rg -n -F '192.0.2.10' /srv/example-app /etc/nginx搜索结果可能含有敏感配置,应在受控环境查看。逐项判断用途后再修改,不要对整个服务器执行全局替换。历史目录名、数据库名、备份记录中的旧地址不一定需要改;前端最好修改源码并重新构建。
九、启动与验证
先验证配置,再按依赖顺序启动:数据库 → 应用运行环境 → 后台服务 → Web 入口 → 定时任务。
sudo nginx -t
sudo systemctl daemon-reload
sudo systemctl start mysqld.service
sudo systemctl start php-fpm.service
sudo systemctl start example-worker.service
sudo systemctl start nginx.service不要过早开启会发邮件、扣款、调用第三方接口或执行破坏性清理的定时任务。应先确认目标地址和业务状态,避免新旧两台同时执行同一任务。
1. 数据核对
备份哈希一致只能证明传输文件一致,还需要检查恢复结果:
- 网站文件数量、哈希、软链接、权限和上传目录。
- 数据库列表、表数量、精确行数以及关键业务记录。
- 在兼容版本和方法下比较业务表校验值。
- 执行数据库支持的完整性检查。
例如,小型 MySQL 数据库可在安排好负载后使用:
mysqlcheck -u admin -p --check example_db表校验方法、锁和性能影响应按数据库版本、存储引擎评估。大库不要直接照搬可能长时间占用资源的检查命令。
2. 服务与端口
systemctl --failed --no-pager
systemctl is-active nginx mysqld php-fpm
ss -lntup
supervisorctl statussystemd 显示 active 不一定说明实际业务进程正常。有些旧式服务脚本退出成功,但守护进程可能没有启动,应同时检查进程、监听端口和日志。
3. 切换 DNS 前验证网站
使用 --resolve,让请求直达新服务器,同时保留正确域名、Host 和 TLS SNI:
curl --resolve blog.example.com:443:198.51.100.20 \
-I https://blog.example.com/不要使用 -k 作为证书验收方式。证书过期或域名不匹配,需要正确处理。
首页返回 200 只是基础检查。还要测试登录、数据库查询、文件上传下载、后台任务、API、WebSocket,以及客户端实际连接。FTP 则应测试登录、TLS 和被动模式传输,不能只看 21 端口。
4. 重启验证
确认服务已按预期启用开机自启,在维护窗口内重启新服务器。重连后再次检查数据库、网站、后台服务、定时任务、挂载和交换空间。
重启前应确保有控制台恢复入口,避免配置错误导致 SSH 无法重新连接。
十、切换 DNS 和客户端地址
正式切换前,应再次确认旧服务器不会产生新写入。如果预同步期间仍有写入,必须停写并做最后一次增量同步或重新导入。
将需要迁移的域名 A 记录指向新 IP,检查是否存在仍指向旧服务器的 AAAA 记录,并同步处理 CDN 或负载均衡源站。
不要假定修改解析控制台中的记录就一定生效:注册商实际委派的 NS 必须正确。迁移 DNS 服务商时,还需要迁移邮件、验证记录等完整配置,并协调已有 DNSSEC 的 DS 记录,防止解析验证失败。
客户端使用旧 IP 时,需要更新地址;使用域名时,通常随 DNS 生效而切换。仍应考虑缓存、长连接和客户端本地配置。
HTTPS 证书也要验证:可安全迁移仍有效且覆盖域名的证书,也可在验证条件具备后重新申请。证书私钥必须限制访问,并确认自动续期任务和部署钩子在新服务器有效。
十一、保留回退能力
切换后保留旧服务器和备份一段观察期,旧业务保持停止或隔离,避免双写。不要立即删除旧数据或释放实例。
回退不是简单把 DNS 改回去:如果新服务器已经接受了写入,必须先处理新数据,否则会丢失切换后的业务记录。应事先定义停写、数据回同步、入口切回和验证步骤。
确认稳定后,再按保留策略处理备份、撤销临时访问、清理迁移凭据,并安排旧实例下线。
十二、如何判断迁移完成
可以把完成状态分成三层:
| 阶段 | 验收内容 |
|---|---|
| 数据与环境恢复 | 文件、数据库、配置和依赖已恢复并核对 |
| 服务运行验证 | 进程、端口、日志、证书和重启自启正常 |
| 业务切换验收 | 域名与客户端已切换,真实业务操作通过,监控稳定 |
只有首页能打开,不能代表全部业务验收完成。记录已测试的范围和未覆盖的功能,才能明确剩余风险。
十三、迁移中容易踩的坑
| 问题 | 改进方法 |
|---|---|
| 打包运行中的数据库文件 | 停库物理备份,或使用数据库支持的一致性备份 |
整体覆盖 /etc、/usr/local | 按清单选择性恢复,保留新主机网络、身份和云代理 |
| 忽略证书和 FTP TLS 文件 | 将证书、私钥和协议实际连接列入验收 |
| 用户名相同但权限异常 | 核对 UID/GID、ACL、SELinux 上下文 |
| 服务显示 active,但端口没监听 | 检查进程、日志和真实连接 |
| 新旧两台同时执行定时任务 | 在明确切换点迁移任务执行权 |
| 只改 DNS A 记录 | 同时检查 NS、AAAA、CDN、DNSSEC 和缓存 |
| 全局替换旧 IP | 根据配置含义逐项修改,保留必要的历史目录与数据 |
| 迁移后立刻删除旧实例 | 保留观察期和可执行的回退方案 |
| 把运维记录直接改成公开博客 | 删除真实标识、凭据和拓扑,使用文档专用示例 |
评论 (0)