PHP网站从一台服务器迁移到另一台服务器,看起来只是把网站文件和数据库复制过去,真正执行时却经常会出现“网页能打开、程序不能登录”“图片全部404”“Cron不执行”“后台500错误”“数据库乱码”甚至邮件突然停止等问题。原因在于,一个PHP网站并不只是代码和MySQL数据库,而是一整套运行环境。PHP版本、扩展、Web服务器、PHP-FPM、数据库版本、文件权限、Rewrite规则、Cron任务、SSL证书和环境变量,任何一个环节不一致,都可能导致迁移后的系统行为发生变化。
最稳妥的方法不是先把DNS指向新服务器,而是先把新服务器完整搭建出来,在旧服务器仍然正常工作的情况下完成数据库、代码和配置迁移,然后使用测试域名、hosts文件或临时访问方式验证,最后才切换DNS。这样即使新服务器出现问题,也不会立即影响正在运行的生产环境。
数据库迁移应该首先确认旧服务器和新服务器的MySQL或MariaDB版本,以及字符集、排序规则、存储引擎和数据库用户权限。对于InnoDB数据库,可以使用类似下面的方式导出:
mysqldump -u old_user -p \
--single-transaction \
--routines \
--triggers \
--events \
--default-character-set=utf8mb4 \
dbname > dump.sql
--single-transaction适合主要由InnoDB组成的数据库,可以在不长时间锁住普通业务表的情况下获得一致性快照。但如果数据库包含MyISAM等非事务表,不能简单认为这个参数可以保证整个数据库在导出期间完全一致。
如果网站数据库比较大,可以考虑直接压缩:
mysqldump -u old_user -p --single-transaction \
--default-character-set=utf8mb4 dbname | gzip > dump.sql.gz
新服务器创建数据库时,应根据原数据库实际使用情况选择字符集和排序规则,而不是机械地套用某一个Collation。现代PHP网站通常使用utf8mb4,但如果旧网站已经依赖特定排序规则,迁移时最好保持兼容。
导入完成后,不要只检查“数据库能不能连接”,还应该检查表数量、关键表记录数、字符集、索引、存储过程、触发器和事件。尤其是SaaS、CMS和新闻网站,Cron、统计表、文章表、用户表以及后台任务表经常决定网站能否真正恢复运行。
文件迁移同样不要简单理解成“把整个/var/www复制过去”。首先应该区分程序代码、用户上传文件、缓存、日志、临时文件以及运行时生成的数据。可以使用rsync进行第一次完整同步:
rsync -aHAX --info=progress2 \
/var/www/old/ \
user@new_server:/var/www/new/
正式切换之前再进行一次增量同步,可以大幅缩短停机窗口。对于上传量较大的网站,尤其要确认迁移期间是否还有新图片、新附件或用户上传文件产生,否则数据库已经切换,文件却停留在旧服务器,就可能出现文章存在但图片丢失的情况。
文件权限不要简单地把整个网站目录全部设置成777,也不要认为所有文件都必须由www-data拥有。更合理的做法是让Web服务器能够读取代码和静态资源,仅对确实需要写入的目录开放写权限,例如上传目录、缓存目录或特定运行时目录。具体用户和组取决于Apache、Nginx、PHP-FPM以及发行版的配置。
例如:
chown -R deploy:www-data /var/www/new
find /var/www/new -type d -exec chmod 755 {} \;
find /var/www/new -type f -exec chmod 644 {} \;
然后仅对需要PHP写入的目录设置适当的组写权限。这样比把整个网站目录交给PHP-FPM写入更加安全。
真正容易被忽略的是运行环境。迁移前最好在旧服务器记录:
php -v
php -m
php --ini
mysql --version
nginx -v
apache2 -v
新服务器逐项核对。PHP大版本发生变化时,不能假设旧代码一定兼容。例如PHP 7时代的一些函数、语法和扩展,在PHP 8环境中可能产生新的错误。mcrypt也不能作为现代PHP服务器的通用安装建议;如果旧程序依赖它,应先确认程序到底需要什么功能,再寻找兼容的替代方案或升级代码。
数据库连接信息也应该从代码中单独检查。现代PHP项目经常使用.env或服务器环境变量保存数据库主机、用户名、密码、数据库名和其他密钥,而不是把密码直接写进php.ini。迁移时必须确认这些环境变量已经在新服务器正确配置,并且.env没有因为权限、路径或部署流程问题而无法读取。
Nginx和Apache配置也必须重新检查。特别是Nginx后面的PHP-FPM Socket,例如:
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
如果新服务器安装的是PHP 8.3,而配置仍然指向PHP 8.2的Socket,网站就可能直接出现502 Bad Gateway。检查时不要只看Nginx配置文件,还应该确认实际运行的PHP-FPM服务:
systemctl status php8.2-fpm
ls -l /run/php/
伪静态规则同样是迁移中的高频故障点。Apache的.htaccess、Nginx的try_files、Rewrite规则以及网站自己的路由机制必须一起验证。对于使用/news/123.html、/post/456.html之类伪静态URL的网站,只要Rewrite没有迁移完整,首页可能正常打开,文章页面却全部404。
Cron任务必须单独迁移。很多网站的新闻抓取、文章生成、缓存清理、统计汇总、邮件发送和数据库维护依赖Cron。尤其要注意Cron执行时的当前工作目录、PHP绝对路径、脚本权限以及环境变量。网页访问正常,并不意味着Cron环境也正常。
上线之前,最好不要立即修改正式DNS,而是先用hosts文件把自己的电脑临时指向新服务器。例如:
NEW_SERVER_IP example.com
NEW_SERVER_IP www.example.com
然后逐项测试首页、登录、后台、数据库读写、图片上传、文章发布、搜索、分页、伪静态URL、Cron任务以及第三方API。对于HTTPS网站,还要检查SSL证书、HTTP到HTTPS跳转、Canonical URL以及Cookie的Secure和SameSite属性。
数据库连接可以直接测试:
mysql -u new_user -p dbname
HTTP层则可以使用:
curl -I https://example.com
如果出现500、502或504,不要盲目修改PHP配置。应该按照链路排查:Nginx或Apache访问日志 → PHP-FPM日志 → PHP应用日志 → 数据库连接 → 外部API。502通常首先意味着Web服务器与PHP-FPM之间出现问题,而500更多时候需要继续检查PHP代码或运行时错误。
DNS切换前还应该考虑TTL和实际缓存情况。正式切换时,如果旧服务器仍然保持运行,可以形成一个短暂的双服务器过渡期。确认新服务器稳定后,再关闭旧服务器,而不是DNS一改就立刻删除旧环境。
迁移完成后,还要重新检查防火墙、SSH密钥、数据库暴露范围、文件权限、SSL自动续期、备份、日志轮转和监控。数据库通常没有必要直接暴露3306端口给公网;如果应用和数据库在同一台服务器上,可以限制数据库监听和防火墙规则。如果数据库需要远程访问,也应该限制来源地址,而不是简单开放整个Internet。
对于生产网站来说,真正可靠的迁移流程可以概括为:先复制环境,再复制数据库和文件,然后进行增量同步,接着测试PHP、Web服务器、数据库、Rewrite、Cron和SSL,最后切换DNS。旧服务器在确认新服务器稳定之前不要删除。
网站搬家最危险的错误,通常不是“文件没复制过去”,而是迁移人员以为文件复制完成就代表网站已经迁移完成。一个成熟的PHP网站实际上由代码、数据库、运行时环境、权限、任务调度、网络配置和外部依赖共同组成。只要按照这些层次逐项验证,迁移就从一次容易出事故的“搬家”,变成一次可以重复执行、可以回滚的部署过程。
PHP 网站搬家到新服务器:数据库、文件和配置应该怎样迁移
图片说明:示意图 图片来源:Public Domain(公有领域)
喜欢这篇报道?
使用下面的功能,方便以后继续阅读和分享 MNewsTV
关于文章收藏
收藏不需要注册帐号,收藏信息仅保存在当前浏览器中。
删除收藏请进入「我的收藏」进行管理。
捐助(Paypal): https://www.paypal.me/observeccp 订阅中国观察电报 Telegram : https://t.me/s/ObserveCCP