WordPress 迁移后 “Permission denied” 报错的完整修复记录

记录一次真实的迁移报错:国内新主机,备份好数据库和网站源码到另一台生产环境恢复站点后前台白屏并爆:

Warning: require(..../wp-includes/class-wp-paused-extensions-storage.php): Failed to open stream: Permission denied in ..../wp-settings.php on line 42
​
Fatal error: Uncaught Error: Failed opening required '..../wp-includes/class-wp-paused-extensions-storage.php' (include_path='.:/....') in ..../wp-settings.php:42
Stack trace:
#0 ..../wp-config.php(102): require_once()
#1 ..../wp-load.php(50): require_once('...')
#2 ..../wp-blog-header.php(13): require_once('...')
#3 ..../index.php(17): require('...')
#4 {main} thrown in ..../wp-settings.php on line 42
​

判断:PHP-FPM 用户(www)对核心目录/文件读权限不足或被 ACL/不可变属性/SELinux 等限制。

先打开面板终端,确认运行用户:

grep -E '^(user|group)\s*=' /www/server/php/80/etc/php-fpm.d/www.conf
# 期望看到:user = www / group = www

若不是 www,就改成 www 并重启:

sed -i 's/^user\s*=.*/user = www/; s/^group\s*=.*/group = www/' /www/server/php/80/etc/php-fpm.d/www.conf
/etc/init.d/php-fpm-80 restart


修复权限与属主(目录 755 / 文件 644)

依据官方建议:目录 755、文件 644;仅极少数目录需要可写(如 wp-content/uploads)。

# 环境变量
SITE=/www/wwwroot/....
​
# 1)标准权限:目录755、文件644
find "$SITE" -type d -exec chmod 755 {} \;
find "$SITE" -type f -exec chmod 644 {} \;
​
# 2)属主属组(以 PHP-FPM 运行用户 www 为例)
chown -R www:www "$SITE"
​
# 3)清理可能的 ACL 与不可变属性
setfacl -Rb "$SITE"        # 清 ACL
chattr -Ri "$SITE"         # 清不可变属性(若磁盘支持)
​
# 4)重启 PHP-FPM 与 Nginx
/etc/init.d/php-fpm-80 restart
/etc/init.d/nginx restart
​
# 5)链路检查(关键文件)
namei -l "$SITE/wp-includes/class-wp-paused-extensions-storage.php"
sudo -u www head -n1 "$SITE/wp-includes/class-wp-paused-extensions-storage.php" >/dev/null && echo OK || echo FAIL
# A. 看看关键路径属主/权限是否已“www 755/644”
ls -ld /www/wwwroot/XXX/www/wwwroot/XXX/wp-includes

可选:排查 open_basedir 是否限制了路径: grep -RIn 'open_basedir' /www/server/php/80/etc/ /www/server/php/80/etc/php.ini

用 WP-CLI 校验/“仅重装核心”

在你的站点目录里做完整性校验

sudo -u www -H wp --path=/www/wwwroot/XXX core verify-checksums

这条命令会把当前 WordPress 版本的官方校验和拉下来,对比你磁盘上的核心文件,能一眼看出哪些文件被改动/缺失。

原文参考:checksums/https://developer.wordpress.org/cli/commands/core/verify-checksums/

一般是会报出有核心文件异常

首先排除核心文件损坏或版本不一致问题

先确定站点正在使用的 WP 版本(即使 WP 现在起不来也能读到):

php -r "include '/www/wwwroot/XXX/wp-includes/version.php'; echo \$wp_version, PHP_EOL;"

在站点目录执行仅重装核心(不覆盖你的主题/插件/上传):

# 把上一步输出的版本号替换到 --version= 后面
sudo -u www -H wp --path="$SITE" core download --force --skip-content --version=6.x.y

仍旧白屏? 可能是缓存了旧错误页

症状:源站日志已不再报错,但浏览器仍显示旧错误。 处理:先清理近期访问出错的 URL;再刷新页面,观察响应头 EO-Cache-Status: MISS(已回源)。


若参照上面的做法还是无法解决,可以参考下另一种更为简单的做法:

http://[https://www.cnblogs.com/Crazy-Liu/p/11229866.html​]

我用于问题排查的脚本(可直接保存为 check.sh在终端执行),xxx需要替换

#!/usr/bin/env bash
DOMAIN="XXX"
SITE="/www/wwwroot/XXX"
WEBUSER="www"
PHPVER="80"
​
set -euo pipefail
say(){{ printf "\n== %s ==\n" "$*"; }}
​
say "基本信息"
uname -a
php -v | head -n1
echo "PHP-FPM sock:" ; ls -l /tmp/php-cgi-${PHPVER}.sock || true
​
say "路径与核心文件存在性"
if [[ -d "$SITE" ]]; then echo "[OK] $SITE 存在"; else echo "[FAIL] 目录不存在:$SITE"; exit 1; fi
for f in wp-config.php wp-settings.php wp-load.php index.php; do
  [[ -f "$SITE/$f" ]] && echo "[OK] 存在 $f" || {{ echo "[FAIL] 缺少 $f"; exit 1; }}
done
​
say "关键文件可读性(以 $WEBUSER 身份)"
sudo -u "$WEBUSER" head -n1 "$SITE/wp-includes/class-wp-paused-extensions-storage.php" >/dev/null \
  && echo "[OK] 可读" || echo "[WARN] 不可读(检查权限/属主/SELinux)"
​
say "权限与属主快照"
namei -l "$SITE/wp-includes/class-wp-paused-extensions-storage.php" | sed 's/^/  /'
​
say "高风险:世界可写(应清理)"
find "$SITE" \( -type d -perm -0002 -o -type f -perm -0002 \) -printf "  %m %u:%g %p\n" || true
​
say "WordPress 核心校验(WP-CLI 可选)"
if command -v wp >/dev/null 2>&1; then
  sudo -u "$WEBUSER" -H wp --path="$SITE" core verify-checksums || echo "[WARN] 校验未通过"
else
  echo "(未安装 wp-cli,跳过校验)"
fi
​
say "HTTP -> HTTPS 跳转检测"
curl -sS -I "http://$DOMAIN" | sed 's/^/  /'
FINAL=$(curl -sSL -o /dev/null -w "%{{url_effective}}" "http://$DOMAIN")
echo "最终到达: $FINAL"
[[ "$FINAL" =~ ^https:// ]] && echo "[OK] 已强制 HTTPS" || echo "[WARN] 未强制 HTTPS"
​
say "安全响应头(HSTS/NoSniff/Frame/Referrer)"
curl -sSI "https://$DOMAIN" | awk -v IGNORECASE=1 '
/^strict-transport-security:/ {{hsts=1}}
/^x-content-type-options:/     {{nosniff=1}}
/^x-frame-options:/            {{xfo=1}}
/^referrer-policy:/            {{rp=1}}
{{print "  " $0}}
END{{
  if(!hsts)   print "[WARN] 缺少 HSTS"; else print "[OK]   存在 HSTS"
  if(!nosniff)print "[WARN] 缺少 X-Content-Type-Options: nosniff"; else print "[OK]   存在 X-Content-Type-Options"
  if(!xfo)    print "[WARN] 缺少 X-Frame-Options/或用 CSP frame-ancestors"; else print "[OK]   存在 X-Frame-Options"
  if(!rp)     print "[WARN] 缺少 Referrer-Policy"; else print "[OK]   存在 Referrer-Policy"
}}'
​
say "混合内容扫描(是否仍引用 http://)"
curl -sSL "https://$DOMAIN" | grep -iEo 'http://[^\"'\'' )]+' | sort -u | sed 's/^/[MIXED] /' || echo "[OK] 未发现 http:// 资源"
​
say "DNS/CNAME 快速查看"
echo "CNAME:" ; dig +short CNAME "$DOMAIN" || true
echo "A/AAAA:" ; dig +short A "$DOMAIN"; dig +short AAAA "$DOMAIN" || true
​
say "PHP-FPM 用户与站点属主对齐情况"
echo "[INFO] 目录属主:$(stat -c %U:%G "$SITE")"
id "$WEBUSER" || true
echo "[TIP] 若属主不是 ${WEBUSER}:${WEBUSER}: chown -R ${WEBUSER}:${WEBUSER} $SITE  (确认无误再执行)"
​
say "Nginx 错误日志最近50行"
tail -n 50 /www/wwwlogs/${DOMAIN}.error.log 2>/dev/null || echo "(未找到日志)"
​
say "体检完成"

执行提示:若出现 ^M(CRLF)行尾导致 command not found,请运行 dos2unix wp_healthcheck.sh 再执行。

注:本文中的命令与配置基于本次修复过程的实测,仅供参考,具体请结合上面官方文档的实践建议。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇