Discuz搬家后域名跳转不生效,指向老域名的301规则几乎都是被DZ自身的默认域名判断覆盖了;先改配置锁,再谈服务器重定向。
很多站长在DZ搬家时,会遇到一个很难受的现象:明明把服务器和域名都迁到了新环境,访问新域名时浏览器地址栏纹丝不动,或者直接提示重定向次数过多,检查了伪静态、.htaccess、Nginx规则,也看不到明显错误,问题其实卡在Discuz! 自身的域名逻辑上。
为什么DZ搬家后跳转到老域名的规则会“失效”
DZ系统和普通的WordPress、帝国CMS不一样,它在安装和后台配置中会记录“网站默认域名”和“应用域名”两组信息,而且这些信息被缓存层、UCenter、数据库同时保存,当你在服务器层面写好了301规则,请求进入DZ程序的那一秒,如果DZ发现当前域名不在它的白名单里,会优先执行自己内部的跳转逻辑,和你写的301打架。
这会导致两种后果:
- 第一种,跳转到老域名的响应头直接成了200,等于告诉搜索引擎“不需要跳转”。
- 第二种,新域名和默认域名来回跳,形成死循环,最终浏览器报错。
关键不是看空间商的配置面板,而是看DZ的全局设置和缓存数据。
DZ搬家域名更换301设置时最容易踩的坑
新手常犯的一个错误,是在旧服务器的.htaccess里写好了301,然后以为搬到新服务器就自动生效,搬家到新服务器后,新服务器的Web环境里根本没有这套规则,你需要重新在Nginx的conf文件或Apache的.htaccess里逐行写一遍。
以Nginx为例,如果你要让新域名跳转到老域名,需要新建一个server块,放在默认server之前:
server {
listen 80;
server_name new.com www.new.com;
return 301 http://old.com$request_uri;
}
这里有一个非常细的坑:DZ本身的伪静态规则是通过rewrite实现的,如果你把这段return写在 DZ的location块内部,会被后续的rewrite规则影响,导致只能返回302甚至完全失效,正确做法是单独监听server_name的域名,并且不套用DZ的PHP处理逻辑。
Apache环境则要在根目录.htaccess的最顶部加这段:
RewriteCond %{HTTP_HOST} ^new\.com$ [NC]
RewriteRule ^(.)$ http://old.com/$1 [R=301,L]
注意,[L]意味着规则到此结束,不会再执行下面DZ自带的伪静态规则,否则会继续向内层转发。
新域名反向跳转老域名:Discuz的域名锁怎么解开
这是让多数人迷茫的一步,当你确认服务器端301已经生效,但访问新域名依然跳不到老域名时,十有八九是DZ的“域名锁”在作祟。
打开新服务器上的config_global.php文件,搜索$_SERVER关键字,你会发现DZ在某些版本里会自动写入这样一行:
$_SERVER['DZ_HOST'] = 'old.com';
这行代码的作用是锁定域名,如果它写的是old.com,DZ会在程序入口处把当前请求域名替换成old.com,那刚才服务器层面的301反而会被覆盖成DZ内部的跳转,把它改成new.com或者直接删除,才能让外部的301规则接管跳转。
接着去后台的全局 -> 域名设置 -> 基本设置,检查“网站默认域名”这一项,如果里面填的是old.com,也要改成new.com,或者清空,这里和config_global.php是两套独立缓存,只改文件不更新后台缓存,同样没效果。
还有一个容易忽略的角落,config/config_ucenter.php里的UC_DOMAIN常量,如果指向还是老域名,UCenter的通信验证会认为你的请求是非法跳转,导致登录态丢失或跳转到后台登录页,把这一项替换成老域名的地址,保持前后端一致。
一步步排查DZ搬家后跳转不生效的五个位置
如果你已经把上面两个配置都改了,还是不生效,别急,按这个顺序再走一遍,多数情况下能定位到问题。
| 排查顺序 | 检查位置 | 常见故障表现 |
|---|---|---|
| 1 | Web服务器规则(Nginx/.htaccess) | 返回404或502,说明规则没加载 |
| 2 | config_global.php域名锁 | 跳转后URL被强制改写成旧域名 |
| 3 | uc_server/data/config.inc.php | 通信失败,登录失效 |
| 4 | 数据库中的siteurl缓存 | 后台显示正常,前台URL还是旧地址 |
| 5 | CDN或本地DNS缓存层 | 部分地区访问新域名直接返回200 |
第一步,在服务器终端执行nginx -t或apachectl -t检查语法,语法通过后,记得systemctl reload nginx或者重启Apache,部分面板环境(如宝塔)会自动覆盖.htaccess,你需要到“站点设置”里重新打开防跨站和伪静态开关。
第二步,打开config_global.php,把$_SERVER['DZ_HOST']赋值行注释掉,同时搜索全局文件里的old.com字符串,通常会出现3-5处,统一替换为老域名(注意区分大小写和带www的变体)。
第三步,登录UCenter后台后,在应用管理列表里,检查应用的主URL是否指向老域名,如果不一致,通信密钥永远验证失败,点击编辑应用,改成新域名的完整URL,并保存两次。
第四步,打开数据库管理工具,执行这条SQL:
SELECT FROM pre_common_setting WHERE skey IN ('sitedomain','siteurl','defaultstatus');
正常情况下,siteurl字段的值应该为http://old.com/,如果是对应的新地址,把它UPDATE回去:
UPDATE pre_common_setting SET svalue='http://old.com/' WHERE skey='siteurl';
这里特别注意,DZ的siteurl会影响后台生成本地化链接,即便301在服务器层生效,也有可能在响应体里夹带新域名的绝对路径搜索引擎判定为软干扰。
第五步,用以下curl命令验证状态:
curl -I http://new.com
输出里第一行必须是HTTP/1.1 301 Moved Permanently,第二行Location:字段明确指向http://old.com/,如果返回的是302或200,请继续检查CDN里的回源规则以及浏览器插件缓存。
从百度GEO角度看DZ搬家后的跳转URL处理
301跳转是搬家后传递权重的最稳妥方案,百度搜索资源平台的抓取规范明确建议,旧域名URL必须通过301状态码指向新URL,而且要保证整站每一条URL都有一一对应的301映射关系,不能只把首页跳过去,内页全部留空。
301与JS跳转对搜索结果的影响
有些人偷懒,用JS跳转或者meta refresh来实现搬家,这在百度眼里是不认可的,因为抓取阶段不执行JavaScript,结果就是:百度蜘蛛访问新域名时,获得的是200状态码的新内容,但老域名上同样的内容还挂着JS跳转,导致蜘蛛认为这是两个站点并存,权重被稀释。
行业共识认为,301跳转对百度权重的保留效率远高于JS跳转,这一点在任何一场站长分享会里都会被反复强调,你可以在Nginx层面把URL中的/archiver/、/forum.php?mod=viewthread等DZ动态路径单独做规则,让每个帖子ID都能对应到老域名的相同路径下。
老域的帖子地址是old.com/thread-123-1-1.html,新域地址是new.com/thread-123-1-1.html,这两条URL的路径是完全一致的,不需要额外写复杂的映射规则,只要在服务器层把整个域名重定向过去,路径会自动继承。
百度搜索资源平台的“站点改版”提交时机
当你确认跳转稳定生效后,可以登录百度搜索资源平台,在搜索服务 -> 站点改版中提交改版申请,业内专家指出,改版工具不是马上生效,需要等待百度抓取后校验,校验的主要依据就是抓取老URL时返回的状态码。
在提交前,请务必先验证两件事:
- 老域名的DNS解析是否已经指向新服务器,避免百度蜘蛛访问老域名时拿到旧的服务器响应。
- 全站所有URL都走了301,并且重定向路径里没有
/index.php等DZ入口文件的二次跳转。
一旦发现百度抓取诊断工具提示“跳转目标不正确”,常见原因是老域名在百度CNAME解析下没有跟随DNS切到新服务器,这种时候,需要先改DNS的TTL值为300,等待缓存过期后,再重新提交改版。
常见问题
为什么DZ搬家后跳转到老域名的响应头是200而不是301
这说明请求在到达服务器规则前就被DZ程序拦截了,检查是否在config_global.php中定义了$_SERVER['DZ_HOST'],让它覆盖了外部跳转;同时清理DZ后台的缓存 -> 清除缓存,包括内存缓存和文件缓存,UCenter那边的data/目录里的临时文件也要手动删除。
DZ搬家到新服务器后老域名直接跳出“重定向次数过多”怎么处理
循环主要是后台“站点默认域名”和新域名不一致造成,先把后台域名设置里的默认域名清空,然后重启Web服务,如果仍然循环,检查老域名的DNS是否还在指向旧服务器,这会让DZ的跳转目标落到一个不存在的新服务器上,反复跟踪地址。
百度收录的URL仍然是老域名,需要等后台改版完成才恢复正常吗
不需要等,你只需要保证老域名上的301规则持续存在,百度蜘蛛会按照新URL抓取并更新收录索引,百度搜索资源平台的改版记录最多作为一个参考,真正的权重转移是通过频繁抓取响应的301状态码来完成的,通常需要等待一个完整的爬取周期。