在 CentOS 7 上用 Nginx + PHP-FPM + MariaDB 搭 ECShop,新手几乎都会卡在 403、Primary script unknown、Session 写不进、目录不可写这几类报错。本文按「配置 → 版本 → 数据库 → 权限 → 时区 → 源」的顺序,把 11 类高频问题一次排清,每类都给出现场报错、根因和可直接照抄的修复命令;文中命令名均标注英文全称(如
chown= change owner),完整清单见文末《附:命令英文全称速查表》。
本文概要:
| 项目 | 内容 |
|---|---|
| 文章主题 | ECShop 在 CentOS 7 + Nginx + PHP-FPM + MariaDB 上的部署报错排查,按问题类型给出根因与修复命令 |
| 所属类别 | Linux 系统运维 → Web 服务部署 → LNMP 排错 |
| 知识关键字 | nginx · php-fpm · SCRIPT_FILENAME · root · chown · chmod · session · date.timezone · mariadb · Remi · CentOS-Vault |
一、环境说明与前置条件
实验环境:CentOS 7.9、Nginx、PHP-FPM、MariaDB、ECShop 4.x。
ECShop 是老程序,PHP 版本兼容是第一条红线:5.6 / 7.2 / 7.3 可正常跑;7.4 起报弃用警告;8.x 直接致命错误。动手前先确认 PHP 版本:
bash
php -v # 看 PHP 版本,决定要不要降级
nginx -v # 看 Nginx 版本
mysql --version # 看 MariaDB 版本
CentOS 7 已停止维护,yum 官方源失效,装包前必须先把源切到可用镜像(见第八章),否则后面所有 yum install 都会失败。
二、Nginx 与 PHP-FPM:3 个配置坑
部署 ECShop 最高频的翻车区:表象是 403 / 空白页 / Primary script unknown,根因几乎都归结为「root 作用域」和「index 指令」。
2.1 Primary script unknown(PHP-FPM 找不到脚本)
报错日志
text
FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream,
client: 10.1.8.12, server: www.zhb.cloud, request: "GET /test.php HTTP/2.0",
upstream: "fastcgi://127.0.0.1:9000", host: "www.zhb.cloud"
根因
Nginx 传给 PHP-FPM 的 SCRIPT_FILENAME 路径不对,PHP-FPM 在自己的文件系统里找不到脚本。三类诱因:
root只写在location /块里、没写在server顶层 →$document_root为空,SCRIPT_FILENAME只拼出/test.php。root写进了某个 location 块内部(块级默认 root) 。root有作用域,只对当前块生效;location /里的 root 不会「继承」给location ~ \.php$,PHP 请求吃不到。- 全局 root 已存在,但某 location 块又写了(默认)root,把全局 root 覆盖掉 。常见于从默认配置复制时残留的
root /usr/share/nginx/html;------若那条路径没有 PHP 文件,$document_root取到错误目录,照样报 Primary script unknown。
⚠️ 注意 :root 一律写 server 顶层,或给每个 location 都显式写 root;别把 root 塞进 location / 当「默认 root」,也别残留 root /usr/share/nginx/html; 偷偷覆盖全局。改完用 nginx -T 2>/dev/null | grep -n root 全局扫一遍确认。
排查 :开 Nginx debug 日志,看实际传出的 SCRIPT_FILENAME:
nginx
location ~ \.php$ {
error_log /var/log/nginx/php-debug.log notice;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
}
bash
grep -i script_filename /var/log/nginx/php-debug.log
若输出只有 /test.php(无目录前缀),就是 root 作用域问题。
解决
把 root 移到 server 块顶层,并确保 fastcgi_param SCRIPT_FILENAME 写在 include fastcgi_params; 之后(后写覆盖前写):
nginx
server {
listen 80;
server_name www.zhb.cloud;
root /website/ecshop; # ← 放这里,全 server 生效
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
}
}
bash
nginx -t && nginx -s reload
2.2 directory index of ".../install/" is forbidden(403)
根因
请求的是目录 /install/,但 Nginx 的 index 指令里没有 index.php,找不到默认索引文件;又因为 autoindex 默认关闭,于是返回 403。index.php 文件本身存在且权限正常。
解决
在 server 块里加 index 指令,把 index.php 放最前:
nginx
index index.php index.html index.htm;
改完 nginx -s reload。/test.php 是具体文件,命中 location ~ \.php$,不涉及 index;/install/ 是目录,必须靠 index 决定首页(详见下方 403 成因图)。
2.3 文件权限链排查
不仅文件本身要有读权限,从根目录到该文件的每一级目录 都必须对 PHP-FPM 用户有 x(进入)权限。任何一级缺 x,即使文件是 777,PHP-FPM 也进不去。
bash
namei -l /website/httpsweb/test.php
text
dr-xr-xr-x root root /
drwxr-xr-x root nginx website
drwxr-xr-x root nginx httpsweb
-rw-r--r-- root nginx test.php
namei -l 逐层列出每级目录的权限与属主,哪一列没有 x 一眼可见。

三、PHP 版本与扩展兼容
3.1 花括号偏移访问弃用(curly braces deprecated)
报错内容
text
Deprecated: Array and string offset access syntax with curly braces is deprecated
in /website/ecshop/includes/lib_base.php on line 1071
根因
PHP 7.4 弃用了用花括号 {} 访问数组/字符串偏移量的写法(如 $str{0}),PHP 8.0 彻底移除。ECShop 老代码大量使用此语法。
| PHP 版本 | 是否报错 |
|---|---|
| 5.3 / 5.4 / 5.6 | 不报 |
| 7.0 ~ 7.3 | 不报 |
| 7.4 | 开始报 Deprecated |
| 8.x | 致命错误 |
⚠️ 注意:ECShop 建议锁 PHP 5.6 或 7.2/7.3,避开 7.4+ 的弃用警告与 8.x 的致命错误。PHP 5.6/7.3 已停止维护,存在安全风险,生产环境先在测试机验证。
解决 :降级 PHP(见 3.2);或把 $str{0} 改成 $str[0],批量查找:
bash
grep -rn '{[0-9]}' /website/ecshop/includes/
3.2 PHP 降级命令(CentOS 7 + Remi)
以从 7.4 降到 5.6 为例:
bash
# 1. 备份配置
cp /etc/php.ini /etc/php.ini.bak
cp -r /etc/php-fpm.d /etc/php-fpm.d.bak
# 2. 卸载当前 PHP
yum remove php-* -y
yum autoremove -y
# 3. 切换仓库
yum-config-manager --disable remi-php74
yum-config-manager --enable remi-php56
# 4. 安装目标版本及常用扩展
yum install -y php php-fpm php-cli php-common php-gd php-mbstring \
php-mysqlnd php-pdo php-xml php-json php-curl php-zip php-opcache
# 5. 启动服务
systemctl start php-fpm
systemctl enable php-fpm
systemctl restart nginx
降到 7.3 则把 remi-php56 换成 remi-php73。
3.3 PHP 7.4 升级命令(Remi 仓库)
bash
yum install -y epel-release
yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum install -y yum-utils
yum-config-manager --enable remi-php74
yum update -y php*
Remi 装的 7.4 配置文件路径变了:
| 文件 | 路径 |
|---|---|
| php.ini | /etc/opt/remi/php74/php.ini |
| php-fpm.conf | /etc/opt/remi/php74/php-fpm.conf |
| pool 配置 | /etc/opt/remi/php74/php-fpm.d/www.conf |
3.4 PHP 常用扩展与 MySQL 组件
Remi 仓库版本切换 速查表
| 命令 | 作用 |
|---|---|
yum-config-manager --enable remi-php56 |
启用 PHP 5.6 仓库 |
yum-config-manager --enable remi-php73 |
启用 PHP 7.3 仓库 |
yum-config-manager --disable remi-php74 |
关闭 PHP 7.4 仓库 |
yum install -y php-<ext> |
安装指定扩展(ext 如 gd/mbstring) |
yum update -y php* |
按当前启用仓库升级全部 PHP 包 |
扩展 速查表
| 扩展 | 作用 |
|---|---|
| php-mysqlnd | MySQL 原生驱动(必装),提供 mysqli 与 pdo_mysql |
| php-pdo | PDO 数据库抽象层 |
| php-gd | 图像处理(验证码、缩略图) |
| php-mbstring | 多字节字符串处理 |
| php-xml | XML 处理 |
| php-curl | HTTP 请求 |
| php-zip | ZIP 压缩 |
| php-opcache | 字节码缓存 |
bash
yum install -y php-cli php-common php-devel \
php-mysqlnd php-pdo \
php-gd php-mbstring php-xml php-bcmath \
php-json php-curl php-zip php-opcache
⚠️ 注意 :不要装
php-pecl-mysql,它在 PHP 7 中已废弃,改用mysqli或PDO_MySQL。
四、MariaDB 安装与连接
4.1 安装与安全初始化
bash
yum install -y mariadb mariadb-server
systemctl start mariadb
systemctl enable mariadb
mysql_secure_installation
mysql_secure_installation 按提示设置 root 密码、移除匿名用户、禁止 root 远程登录、删除 test 库。
4.2 为 ECShop 创建数据库和用户
sql
CREATE DATABASE ecshop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'ecshop'@'localhost' IDENTIFIED BY 'ecshop_pass';
GRANT ALL PRIVILEGES ON ecshop.* TO 'ecshop'@'localhost';
FLUSH PRIVILEGES;
4.3 PHP 连接测试
bash
cat > /website/ecshop/test_db.php << 'EOF'
<?php
$conn = new mysqli("localhost", "ecshop", "ecshop_pass", "ecshop");
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
echo "数据库连接成功";
$conn->close();
EOF
访问后确认成功,测试完删除该文件 。MariaDB 直接兼容 PHP 标准的 MySQL 扩展,无需专用「php-mariadb」包;推荐 php-mysqlnd,避免使用已废弃的 php-mysql。
五、Session 与会话问题
5.1 session_start(): open(...) failed: Permission denied(13)
报错内容
text
Warning: session_start(): open(/var/lib/php/session/sess_xxx, O_RDWR) failed:
Permission denied (13) in /website/ecshop/install/index.php on line 23
根因 :PHP-FPM 运行用户对 /var/lib/php/session/ 目录没有写权限。
⚠️ 注意:Session 目录和 ECShop 项目目录是两回事,需分别处理------项目目录按第六章改属主,Session 目录单独改这里。
bash
ps aux | grep php-fpm # 确认 PHP-FPM 运行用户(如 nginx)
chown -R nginx:nginx /var/lib/php/session
chmod 700 /var/lib/php/session
systemctl restart php-fpm
5.2 连锁反应:Invalid argument supplied for foreach()
Session 写入失败后,依赖 Session 的变量为空,导致 foreach 遍历空值报 Warning。Session 权限修复后,此警告通常自动消失。
六、ECShop 目录权限问题
6.1 安装检测大量目录「不可写」
现象 :安装向导检测结果中,cert、images、data、temp、themes/default/ 下所有 .dwt 和 .lbi 文件全部显示「不可写」。
根因 :PHP-FPM 运行用户既不是这些目录的属主,也不在允许写入的组里。ECShop 后台的模板编辑功能需要写 .dwt 和 .lbi 文件,所以这些文件必须对 PHP-FPM 用户可写。
⚠️ 注意:把整个 ECShop 目录属主统一为 PHP-FPM 用户是最省事的做法;Session 目录(第五章)要单独处理,不要一并 chown 到项目目录里。
6.2 权限修复命令
目录权限修复 速查表
| 命令 | 作用 |
|---|---|
chown -R nginx:nginx /website/ecshop |
递归改项目目录属主为 PHP-FPM 用户 |
find /website/ecshop -type d -exec chmod 755 {} \; |
目录权限设为 755 |
find /website/ecshop -type f -exec chmod 644 {} \; |
文件权限设为 644 |
chmod -R 775 /website/ecshop/cert |
可写目录放宽到 775 |
bash
chown -R nginx:nginx /website/ecshop
find /website/ecshop -type d -exec chmod 755 {} \;
find /website/ecshop -type f -exec chmod 644 {} \;
chmod -R 775 /website/ecshop/cert
chmod -R 775 /website/ecshop/images
chmod -R 775 /website/ecshop/data
chmod -R 775 /website/ecshop/temp
chmod -R 775 /website/ecshop/themes
systemctl restart php-fpm
七、时区问题
7.1 date(): It is not safe to rely on the system's timezone settings
报错内容
text
Warning: date(): It is not safe to rely on the system's timezone settings.
You are *required* to use the date.timezone setting or the date_default_timezone_set() function.
...
in /website/ecshop/includes/cls_mysql.php on line 161
根因 :PHP 未配置默认时区,调用 date() 时产生警告,打断 ECShop 安装数据流程。
⚠️ 注意 :
date.timezone必须在 php.ini 配置,否则安装流程会被警告打断;临时在代码里加date_default_timezone_set()只是应急,重启 PHP 后仍可能复发。
7.2 两种修法
推荐(一劳永逸):改 php.ini 后重启服务。
ini
date.timezone = Asia/Shanghai
bash
systemctl restart php-fpm
systemctl restart nginx
临时 :在 /website/ecshop/includes/cls_mysql.php 顶部 <?php 后加:
php
date_default_timezone_set('Asia/Shanghai');
八、YUM 源问题(CentOS 7 EOL 后更换源)
CentOS 7 已于 2024-06-30 停止维护,官方镜像源失效。装包前先切源。
方案一:华为云 EPEL 源
bash
mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.bak
wget -qO /etc/yum.repos.d/epel.repo https://mirrors.myhuaweicloud.com/repo/epel-7.repo
yum clean metadata
yum makecache
方案二:切换 CentOS Vault 归档源
bash
mkdir -p /etc/yum.repos.d/bak
mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bak/
cat > /etc/yum.repos.d/CentOS-Vault.repo << 'EOF'
[base]
name=CentOS-7.9.2009 - Base
baseurl=https://repo.huaweicloud.com/centos-vault/7.9.2009/os/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://repo.huaweicloud.com/centos-vault/RPM-GPG-KEY-CentOS-7
[updates]
name=CentOS-7.9.2009 - Updates
baseurl=https://repo.huaweicloud.com/centos-vault/7.9.2009/updates/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://repo.huaweicloud.com/centos-vault/RPM-GPG-KEY-CentOS-7
[extras]
name=CentOS-7.9.2009 - Extras
baseurl=https://repo.huaweicloud.com/centos-vault/7.9.2009/extras/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://repo.huaweicloud.com/centos-vault/RPM-GPG-KEY-CentOS-7
EOF
yum clean all
yum makecache
九、证书问题
9.1 导入 .crt 报 Import failed: Invalid value for field
根因 :导入的是只有公钥的 .crt 文件,缺少私钥信息;或自签名证书某些字段不符合 Windows 严格校验。
解决
需要部署到服务器:用 OpenSSL 合并为 .pfx:
bash
openssl pkcs12 -export -out www.zhb.cloud.pfx \
-inkey www.zhb.cloud.key -in www.zhb.cloud.crt
只是让浏览器信任:导入到「受信任的根证书颁发机构」存储区。

十、其他问题
10.1 Shell 引号嵌套导致 PHP 文件内容错误
错误命令
bash
echo "<?=echo "php page"?>" > php_echo.php
外层双引号与内层双引号冲突,Shell 解析错乱;且 <?= 本身等价于 echo,再写 echo 会变成 echo echo,PHP 语法错误。
正确写法
bash
echo '<?= "php page" ?>' > php_echo.php
或:
bash
echo '<?php echo "php page"; ?>' > php_echo.php
十一、部署检查清单
部署完逐项核对,避免上线后返工:

- Nginx
root写在server块顶层(不在 location 块内当默认 root) -
fastcgi_param SCRIPT_FILENAME在include fastcgi_params;之后 -
index指令包含index.php且在最前 - PHP-FPM 与 Nginx 用户一致,目录权限正确
-
/var/lib/php/session属主为 PHP-FPM 用户且可写 - ECShop 目录属主统一为 PHP-FPM 用户
-
cert、images、data、temp、themes可写 - php.ini 配置
date.timezone = Asia/Shanghai - MariaDB 已创建 ECShop 数据库与用户
-
php-mysqlnd、php-gd、php-mbstring等扩展已安装 - YUM 源已切换至可用镜像(EPEL 或 Vault)
- PHP 版本与 ECShop 兼容(5.6 或 7.2/7.3)
附:命令英文全称速查表
| 命令 / 缩写 | 英文全称 / 原意 | 作用 |
|---|---|---|
| nginx | engine x | 高性能 Web 服务器 / 反向代理 |
| php-fpm | PHP F astCGI P rocess Manager | PHP FastCGI 进程管理器 |
| fastcgi | F ast C ommon G ateway Interface | 与 PHP 等后端通信的协议 |
| chown | ch ange owner | 修改文件属主 |
| chmod | ch ange mode | 修改文件权限 |
| session | session(会话) | 服务器端用户会话存储 |
| mariadb | Ma riaDB(MySQL 分支,取名自创始人之女) | 关系型数据库 |
| yum | Y ellowdog U pdater Modified | RPM 包管理器 |
| epel | E xtra P ackages for E nterprise Linux | 企业版 Linux 额外软件包 |
| Remi | Rémi 的 RPM 仓库(命名自维护者 Rémi Collet) | PHP 多版本仓库 |
📚 参考资料(官方文档 · 中英双语)
总结:ECShop 在 CentOS 7 + LNMP 上的报错,九成集中在「root 作用域 / index 指令 / PHP 版本 / 目录权限 / 时区」五件事。先把 root 提到 server 顶层、PHP 锁在 5.6 或 7.2/7.3、目录属主统一给 PHP-FPM 用户、php.ini 配好时区,再按第十一章清单逐项核对,基本一次就能跑通。你部署时还踩过哪些坑?评论区贴出报错一起看。
