一边装一边报错:CentOS 7 + LNMP 跑 ECShop 的常见故障与解法

在 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 在自己的文件系统里找不到脚本。三类诱因:

  1. root 只写在 location / 块里、没写在 server 顶层 → $document_root 为空,SCRIPT_FILENAME 只拼出 /test.php。
  2. root 写进了某个 location 块内部(块级默认 root) 。root 有作用域,只对当前块生效;location / 里的 root 不会「继承」给 location ~ \.php$,PHP 请求吃不到。
  3. 全局 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 配好时区,再按第十一章清单逐项核对,基本一次就能跑通。你部署时还踩过哪些坑?评论区贴出报错一起看。

相关推荐
遇印记1 小时前
数据通信初步
运维·服务器·网络·windows·学习
学linux的QQ蛋1 小时前
图解 Linux 驱动编译进内核的完整工作流程
linux·运维·服务器
承渊政道1 小时前
Linux网络学习【UDP Socket编程实战:网络命令与客户端访问Linux验证】
linux·网络·学习·ubuntu·编程实战·udp socket
A-刘晨阳1 小时前
GitLab + ArgoCD 实现 Kubernetes GitOps 自动化部署
运维·人工智能·git·kubernetes·自动化·云计算·argocd
print_Hyon1 小时前
【ENSP】DHCP 基础实验(路由器作为 DHCP 服务器,接口地址池模式)
运维·服务器·智能路由器
程序员-Benothing1 小时前
正则表达式详解:BRE、ERE、PCRE语法与实战案例
linux·运维·服务器
软件架构师-叶秋1 小时前
V853方案之ubuntu开发环境搭建
linux·运维·服务器·全志·v853
yt004yt1 小时前
园区绿岛 VOC 治理,能碳一体化系统设计思路分享
大数据·运维
lzx_0021 小时前
Linux 开发工具(二) 简单认识一下编辑器 —— vim
linux·编辑器·vim