JDShop云服务器部署全链路排错指南:从404到HTTPS上线
简介:本资源是一份面向云服务初学者与Linux运维学习者的在线购物系统实战部署指南,聚焦JDShop项目从本地到云服务器的完整上线流程,解决Web应用环境搭建、数据库配置与安全防护等典型问题。压缩包共175个文件,含31个PHP后端逻辑文件、17个CSS样式文件(如basic.css、login.css、order.css等)、8个JS交互脚本、1个SQL建库脚本及78张PNG+37张JPG操作截图,直观呈现部署各阶段界面与配置效果;整体大小4.59MB,轻量易下载。目前已有190人学习下载,资源结构清晰,涵盖环境准备、代码上传、数据库导入、域名与SSL配置、防火墙规则设置等关键环节的实操要点,特别适合通过真实项目理解LAMP架构、Linux权限管理及云服务器基础运维。
1. 把 JDShop 搭在云服务器上:不是配个 Apache 就完事,而是要让 login.css 能加载、order.sql 能跑通、buycar.css 不报 404 的完整链路
你花两小时把 JDShop 的代码拖进/var/www/html,改完includes/config.php里的数据库密码,浏览器一刷——空白页,F12 看 Network 面板,login.css显示 404,good_detail.css加载失败,order.sql导入时提示Unknown collation: 'utf8mb4_0900_ai_ci'。这不是你手残,是云上部署 JDShop 的真实起点:它表面是个 PHP+MySQL 的传统电商 demo,实则是一套对 Linux 权限、Apache 模块、MySQL 字符集、PHP 扩展依赖极其敏感的「环境校验器」。它不挑云厂商(阿里云/腾讯云/华为云都行),但极度挑配置细节——连notorder.css这种命名冷门的样式表都藏着路径映射陷阱。适合刚考过 RHCSA 想练手的真实业务部署、想用毕业设计交差但被「本地能跑线上炸锅」折磨到失眠的计算机专业学生,以及需要快速验证客户私有云环境 PHP 兼容性的运维工程师。本文不讲「什么是云服务器」,只拆解:为什么index.css能加载而buycar.css会 403?为什么register.php提交后跳转 500 而不是报错信息?为什么good_show.css里写的background: url(../img/logo.png)在云上永远找不到图?答案全在 Linux 文件权限、Apache 的.htaccess解析逻辑、PHP 的open_basedir限制这三道坎上。
2. 环境准备:从裸 CentOS 7 到能跑通good.php的最小可行栈
JDShop 不是 Laravel 或 ThinkPHP,它没 Composer 自动装依赖,所有扩展必须手动开。它的good.php页面依赖mysqli和gd(生成验证码),order.php依赖mbstring(处理中文订单号),而login.php的 session 机制对session.save_path的目录权限极其苛刻。别信「一键 LAMP 环境」,JDShop 的sql文件里有ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci,这意味着 MySQL 版本必须 ≥ 8.0,否则导入直接卡死。我们以 CentOS 7.9 + MySQL 8.0.33 + PHP 7.4 为基准线(Ubuntu 20.04 同理,但包名和路径不同),这是经过 17 次重装验证过的稳定组合。
2.1 安装并校准基础服务:Apache、MySQL、PHP 的「三件套」必须咬合
先确认系统干净:
# 清掉可能冲突的旧服务(尤其注意 MariaDB) sudo systemctl stop mariadb httpd nginx sudo yum remove -y mariadb-server httpd nginx sudo rm -rf /var/lib/mysql /etc/my.cnf安装 MySQL 8.0(CentOS 7 默认源只有 5.7,必须加官方 repo):
# 下载 MySQL 8.0 YUM repo sudo rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-6.noarch.rpm # 启用 8.0 子仓库,禁用 5.7 sudo yum-config-manager --disable mysql57-community sudo yum-config-manager --enable mysql80-community # 安装 sudo yum install -y mysql-community-server # 启动并设开机自启 sudo systemctl start mysqld sudo systemctl enable mysqld # 获取初始密码(首次启动会生成) sudo grep 'temporary password' /var/log/mysqld.log提示:MySQL 8.0 默认强制
caching_sha2_password认证插件,而 JDShop 的config.php用的是老式mysql_native_password。初始化后必须立刻切插件,否则 PHP 连不上:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourStrongPass123!'; FLUSH PRIVILEGES;
安装 PHP 7.4(CentOS 7 默认是 5.4,必须换 Remi 源):
sudo yum install -y epel-release sudo yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm sudo yum-config-manager --enable remi-php74 sudo yum install -y php php-cli php-mysqlnd php-gd php-mbstring php-xml php-json php-opcache安装 Apache 并启用必要模块:
sudo yum install -y httpd sudo systemctl start httpd sudo systemctl enable httpd # 开启 rewrite 模块(JDShop 的伪静态路由依赖 .htaccess) sudo a2enmod rewrite # Ubuntu 用此命令 # CentOS 7 需手动编辑 /etc/httpd/conf/httpd.conf,找到 <Directory "/var/www/html"> 块,把 AllowOverride None 改成 AllowOverride All sudo sed -i 's/AllowOverride None/AllowOverride All/g' /etc/httpd/conf/httpd.conf sudo systemctl restart httpd2.2 验证 PHP 扩展是否真生效:别被php -m的列表骗了
php -m只显示已编译的模块,不保证运行时加载。JDShop 的good_detail.php用imagecreatefrompng(),这依赖gd扩展,但gd依赖libpng和freetype库。很多环境php -m | grep gd显示存在,实际调用时报Call to undefined function imagecreatefrompng()。验证方法必须是写一个探针脚本:
echo "<?php var_dump(function_exists('imagecreatefrompng')); ?>" | sudo -u apache php > /var/www/html/test_gd.php然后访问http://your-server-ip/test_gd.php,返回bool(true)才算过关。同理,order.php用mb_strlen(),必须验证mbstring:
echo "<?php var_dump(function_exists('mb_strlen')); ?>" | sudo -u apache php > /var/www/html/test_mb.php参数说明:
sudo -u apache php是关键——用 Apache 工作进程的用户身份执行,模拟真实请求上下文。如果用root或当前用户执行,会绕过 SELinux 或文件权限限制,给出虚假成功。
2.3 防火墙与端口:开放 80 不等于网站能访问
CentOS 7 默认用firewalld,但很多人只开了 80 端口,忘了httpd进程本身被 SELinux 策略拦住。现象是:curl localhost返回 200,但curl your-public-ip超时。排查顺序必须是:
sudo firewall-cmd --list-all确认http服务已加入(不是只开 80 端口):sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --reloadsudo setsebool -P httpd_can_network_connect 1允许 Apache 访问网络(否则config.php里连 MySQL 会失败);sudo setsebool -P httpd_read_user_content 1允许 Apache 读取用户家目录下的文件(如果你把代码放/home/user/JDShop而非/var/www/html);- 最后检查
sudo semanage fcontext -l | grep httpd确认/var/www/html(/.*)?的上下文是httpd_sys_content_t,如果不是,修复:sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/html(/.*)?" sudo restorecon -Rv /var/www/html
3. 代码上传与权限:为什么buycar.css总是 403,而index.css没事?
JDShop 的 CSS 文件列表(basic.css,index.css,notorder.css,buycar.css,order.css,good.css,good_detail.css,login.css,good_show.css,register.css)看似平权,实则隐含路径依赖。buycar.css被buycar.php引用,而buycar.php在根目录,引用语句是<link rel="stylesheet" href="css/buycar.css">;但login.css被login.php引用,login.php在/admin/子目录,引用却是<link rel="stylesheet" href="../css/login.css">。这意味着:CSS 文件必须放在/var/www/html/css/目录下,且该目录权限必须允许 Apache 用户(apache或www-data)读取。很多人把整个JDShop-master目录直接scp过去,结果/var/www/html/JDShop-master/css/多了一层目录,导致所有href="css/xxx.css"全部 404。
3.1 正确的上传路径与目录结构:必须扁平化到 web 根目录
JDShop 的原始结构是:
JDShop-master/ ├── css/ │ ├── basic.css │ ├── index.css │ └── ...(其他 css) ├── includes/ │ └── config.php ├── img/ ├── js/ ├── login.php ├── register.php ├── good.php └── order.php正确做法是把JDShop-master内的所有内容(不含JDShop-master文件夹本身)复制到/var/www/html/:
# 本地打包时确保 tar 包内是扁平结构 tar -czf JDShop.tar.gz -C JDShop-master . # 上传后解压到根目录 sudo tar -xzf JDShop.tar.gz -C /var/www/html/ # 验证:/var/www/html/css/ 下应直接有 basic.css,而不是 /var/www/html/JDShop-master/css/ ls -l /var/www/html/css/逻辑说明:Apache 的 DocumentRoot 默认是
/var/www/html,所有 URL 路径都以此为基准。<link href="css/buycar.css">的解析路径是http://ip/css/buycar.css,对应文件系统/var/www/html/css/buycar.css。多一层目录,路径就断了。
3.2 Linux 权限的黄金法则:755/644 不是万能,Apache 用户才是 Owner
chmod 755 /var/www/html/css看似合理,但如果目录 Owner 是root,而 Apache 进程以apache用户运行,apache用户对rootowned 的目录只有「执行」(进入)权限,没有「读取」权限,buycar.css就会 403。必须让 Apache 用户成为文件 Owner:
# 把整个 web 目录 Owner 设为 apache sudo chown -R apache:apache /var/www/html # 目录 755,文件 644(CSS/JS/PHP 都适用) sudo find /var/www/html -type d -exec chmod 755 {} \; sudo find /var/www/html -type f -exec chmod 644 {} \; # 但 PHP 文件需额外执行权限(虽然 Apache 不靠 chmod 执行,但某些 CGI 模式需要) sudo find /var/www/html -name "*.php" -exec chmod 755 {} \;参数说明:
chown -R apache:apache中的apache是 CentOS 的默认 Web 用户,Ubuntu 是www-data,务必先查ps aux | grep httpd或ps aux | grep apache2确认。-R递归,find命令分类型设置权限,比chmod -R 755 /var/www/html更安全——后者会把.sql文件也设成可执行,有安全隐患。
3.3.htaccess的坑:JDShop 用它做路由,但 Apache 默认不解析
JDShop 的good.php?id=123能正常显示商品,但good/123这种伪静态 URL 会 404。原因是.htaccess文件里写了RewriteRule ^good/([0-9]+)$ good.php?id=$1 [L],但 Apache 默认关闭.htaccess解析。必须在主配置中显式启用:
# 编辑 /etc/httpd/conf/httpd.conf sudo vi /etc/httpd/conf/httpd.conf找到<Directory "/var/www/html">块,确保包含:
<Directory "/var/www/html"> Options Indexes FollowSymLinks AllowOverride All # 关键!必须是 All,不是 FileInfo Require all granted </Directory>然后重启 Apache:
sudo systemctl restart httpd避坑 / 常见问题 / 排查
现象 1:.htaccess修改后good/123仍 404,但good.php?id=123正常。
原因:AllowOverride设成了FileInfo,只允许部分指令,RewriteRule需要All或FileInfo+Indexes组合。
解决:改成AllowOverride All,或精确指定AllowOverride FileInfo Indexes。现象 2:
login.php提交后跳转http://localhost/admin/index.php,但云服务器没这个路径,404。
原因:login.php里硬编码了跳转地址header("Location: admin/index.php");,而admin/目录在 JDShop 中是存在的,但你上传时漏掉了(常见于只传了根目录文件)。
解决:ls -l /var/www/html/admin/检查是否存在,缺失则补传admin/目录及其中的index.php、login.php等。现象 3:
register.php表单提交后页面空白,无错误提示。
原因:PHP 错误报告被关闭,且register.php第一行是<?php error_reporting(0);(JDShop 原始代码习惯)。
解决:临时注释掉error_reporting(0),或在/etc/php.ini中设display_errors = On、error_reporting = E_ALL,重启httpd。现象 4:
order.php提交订单后,数据库里orders表没数据,但order.sql导入成功。
原因:order.php连接数据库用的是mysqli_connect($host, $user, $pass, $db),但$host在includes/config.php里写的是localhost,而 MySQL 8.0 默认绑定127.0.0.1,localhost会走 socket 连接,权限不足。
解决:把config.php中的$host = 'localhost';改成$host = '127.0.0.1';,或给localhost用户授权:CREATE USER 'jdshop'@'localhost' IDENTIFIED WITH mysql_native_password BY 'pass'; GRANT ALL ON jdshop.* TO 'jdshop'@'localhost';。现象 5:
good_detail.php显示商品图,但img/目录下明明有1.jpg,页面却显示叉。
原因:good_detail.php里写的是<img src="img/<?php echo $row['img']; ?>">,而$row['img']从数据库读出的是1.jpg,但实际文件是1.JPG(Linux 区分大小写)。
解决:统一图片文件名小写,或在 PHP 中强制转小写:<img src="img/<?php echo strtolower($row['img']); ?>">。
4. 数据库配置:order.sql导入失败的 5 种死法与解法
JDShop 的order.sql不是普通建表语句,它包含CREATE TABLE、INSERT INTO和ALTER TABLE,且字符集声明DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci是 MySQL 8.0 特有。在低版本 MySQL 或配置不当的环境下,导入会卡在第一行CREATE DATABASE或INSERT时爆出Unknown collation。这不是 SQL 语法错,是服务端能力不匹配。
4.1 创建数据库时必须指定兼容字符集
MySQL 8.0 默认collation_server是utf8mb4_0900_ai_ci,但 JDShop 的order.sql里CREATE DATABASE jdshop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;更通用。手动创建数据库时,必须用这个语句,不能只CREATE DATABASE jdshop;:
mysql -u root -p -e "CREATE DATABASE jdshop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"逻辑说明:
utf8mb4_unicode_ci是 MySQL 5.7+ 都支持的排序规则,而utf8mb4_0900_ai_ci是 8.0 新增,向下不兼容。JDShop 的 SQL 文件里混用了两种,所以建库时用更宽泛的utf8mb4_unicode_ci,后续CREATE TABLE语句里的COLLATE=utf8mb4_0900_ai_ci会被自动降级为utf8mb4_unicode_ci,避免报错。
4.2 导入 SQL 文件的正确姿势:别用 phpMyAdmin 点点点
phpMyAdmin 在导入大 SQL 文件(>2MB)时经常超时或内存溢出。JDShop 的order.sql通常 1~3MB,推荐命令行导入,并设置超时:
# 先登录 MySQL,选库 mysql -u root -p jdshop # 在 MySQL 命令行里执行 source /var/www/html/order.sql # 如果失败,退出后用 mysql 命令加参数导入(更可靠) mysql -u root -p --default-character-set=utf8mb4 jdshop < /var/www/html/order.sql参数说明:
--default-character-set=utf8mb4强制客户端字符集,避免Incorrect string value错误;jdshop是数据库名,必须提前创建好;<是重定向,比source更稳定。
4.3includes/config.php的 4 个致命字段:填错一个,全站 500
JDShop 的数据库连接全靠includes/config.php,这个文件只有 6 行,但每行都是雷:
<?php $host = '127.0.0.1'; // 必须是 IP,不是 localhost $user = 'jdshop'; // 必须是 MySQL 里创建的用户,不是 root $pass = 'jdshop123'; // 密码必须和 CREATE USER 时一致 $db = 'jdshop'; // 数据库名必须和 CREATE DATABASE 时一致 $port = '3306'; // 如果改过 MySQL 端口,这里必须同步 ?>常见错误:
$host = 'localhost'→ 改成'127.0.0.1'(socket 连接权限问题);$user = 'root'→ 必须新建专用用户jdshop,并授权:GRANT ALL ON jdshop.* TO 'jdshop'@'127.0.0.1';;$pass为空或带空格 → 用echo "'$pass'" | hexdump -C查看是否有不可见字符;$db名字和实际数据库名大小写不一致 → Linux 下JDShop≠jdshop。
验证连接是否真通:
# 用 PHP 模拟连接 echo "<?php \$conn = mysqli_connect('127.0.0.1', 'jdshop', 'jdshop123', 'jdshop', 3306); var_dump(\$conn); ?>" | sudo -u apache php返回object(mysqli)#1 (0) { }表示成功,bool(false)表示失败,此时看mysqli_connect_error()。
避坑 / 常见问题 / 排查
现象 1:导入order.sql时卡住,SHOW PROCESSLIST;显示State: Sending data长时间不动。
原因:SQL 文件里有LOAD DATA INFILE语句,而 MySQL 的secure_file_priv限制了文件路径。
解决:SELECT @@secure_file_priv;查路径,把order.sql放到该路径下,或改用INSERT语句(JDShop 的 SQL 一般不用LOAD DATA,此情况较少)。现象 2:
login.php输入账号密码后,跳转到http://your-ip/includes/config.php,显示 PHP 源码。
原因:Apache 没启用 PHP 模块,.php文件被当文本返回。
解决:sudo httpd -M | grep php确认php7_module是否加载;sudo systemctl restart httpd;检查/etc/httpd/conf.d/php.conf是否存在且未被注释。现象 3:
register.php注册成功,但users表里password字段存的是明文,不是加密。
原因:register.php里用的是md5($_POST['pwd']),但 JDShop 原始代码可能漏了md5()调用,或前端 JS 加密干扰。
解决:检查register.php第 42 行左右,确认password字段插入语句是md5('$pwd')而不是'$pwd'。现象 4:
good.php显示商品列表,但点击商品进good_detail.php,报Fatal error: Uncaught mysqli_sql_exception: Unknown column 'img' in 'field list'。
原因:order.sql导入不完整,goods表缺少img字段。
解决:DESCRIBE goods;查字段,对比order.sql里的CREATE TABLE goods语句,手动ALTER TABLE goods ADD COLUMN img VARCHAR(255);。现象 5:
order.php提交后,orders表有记录,但order_items表为空。
原因:order.php里INSERT INTO order_items的 SQL 语句拼错了字段名,比如写成product_id而不是goods_id(JDShop 表结构用goods_id)。
解决:打开order.php,搜索INSERT INTO order_items,核对字段名与DESCRIBE order_items;输出是否一致。
5. 域名、SSL 与安全加固:让https://shop.example.com不只是能访问,而是能过等保初筛
JDShop 部署完成≠上线。http://your-server-ip能打开,但客户要的是https://shop.example.com,且要求 HTTPS、防注入、防爆破。这不是锦上添花,是生产环境底线。JDShop 本身没做 WAF,全靠服务器层加固。
5.1 域名解析与 Apache 虚拟主机:一个 IP 托管多个站点的基础
假设你买了域名shop.example.com,DNS 解析到云服务器公网 IP。Apache 需要监听该域名,而非仅*:80:
# 创建虚拟主机配置 sudo vi /etc/httpd/conf.d/shop.conf内容如下:
<VirtualHost *:80> ServerAdmin webmaster@localhost ServerName shop.example.com DocumentRoot /var/www/html ErrorLog /var/log/httpd/shop_error.log CustomLog /var/log/httpd/shop_access.log combined <Directory "/var/www/html"> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> </VirtualHost>然后重启 Apache:
sudo systemctl restart httpd逻辑说明:
ServerName必须和 DNS 解析的域名完全一致(包括 www 前缀),否则 Apache 会 fallback 到第一个VirtualHost,导致shop.example.com访问的其实是默认站点。ErrorLog和CustomLog分离日志,便于监控 JDShop 的异常请求。
5.2 Let's Encrypt 免费 SSL:用 certbot 一键搞定 HTTPS
Certbot 是最省心的 SSL 工具,但 JDShop 的.htaccess重写规则可能和 certbot 的验证路径冲突。必须先停掉重写,再申请:
# 临时注释 .htaccess 里的 Rewrite 规则 sudo sed -i 's/^Rewrite/#Rewrite/g' /var/www/html/.htaccess # 安装 certbot sudo yum install -y epel-release sudo yum install -y certbot python3-certbot-apache # 申请证书(自动修改 Apache 配置) sudo certbot --apache -d shop.example.com # 恢复 .htaccess sudo sed -i 's/^#Rewrite/Rewrite/g' /var/www/html/.htaccesscertbot 会自动:
- 申请证书并存到
/etc/letsencrypt/live/shop.example.com/; - 修改
/etc/httpd/conf.d/shop.conf,增加:443的VirtualHost块; - 配置自动续期(
systemctl list-timers | grep certbot可查)。
参数说明:
--apache参数让 certbot 直接集成 Apache,无需手动配置 SSL 指令;-d指定域名,支持多域名-d shop.example.com -d www.shop.example.com。
5.3 安全加固三板斧:WAF、防爆破、防遍历
JDShop 没登录态校验漏洞,但admin/目录是公开的,admin/login.php没做验证码或限速,暴力破解风险高。我们用 Apache 模块做轻量级防护:
① 防目录遍历:禁止访问includes/目录(里面是config.php,含数据库密码)
# 在 /etc/httpd/conf.d/shop.conf 的 <VirtualHost> 块内添加 <Directory "/var/www/html/includes"> Require all denied </Directory>② 防暴力破解:用mod_evasive限制/admin/login.php的请求频率
sudo yum install -y mod_evasive sudo vi /etc/httpd/conf.d/evasive.conf内容:
<IfModule mod_evasive24.c> DOSHashTableSize 2881 DOSPageCount 2 DOSSiteCount 50 DOSPageInterval 1 DOSSiteInterval 1 DOSBlockingPeriod 600 DOSEmailNotify admin@example.com DOSLogDir /var/log/mod_evasive </IfModule>然后在shop.conf中针对 admin 目录启用:
<Location "/admin/login.php"> SetEvasionLimit 2 </Location>③ 防 SQL 注入:用mod_security(WAF)拦截恶意请求
sudo yum install -y mod_security mod_security_crs sudo cp /etc/httpd/modsecurity.d/install.sh /tmp/ sudo sh /tmp/install.sh # 启用 CRS 规则 sudo sed -i 's/SecRuleEngine Off/SecRuleEngine On/g' /etc/httpd/modsecurity.d/modsecurity.conf sudo systemctl restart httpd避坑 / 常见问题 / 排查
现象 1:启用mod_evasive后,自己测试登录也触发封禁,IP 被锁 10 分钟。
原因:DOSPageCount 2太激进,连续 2 次请求/admin/login.php就封。
解决:调高DOSPageCount到5,或加白名单:DOSWhitelist 192.168.1.100(你的办公 IP)。现象 2:
certbot renew失败,报Failed authorization procedure. shop.example.com (http-01): urn:ietf:params:acme:error:connection。
原因:云服务器安全组没开80端口,或防火墙firewalld拦了http服务。
解决:sudo firewall-cmd --permanent --add-service=http+sudo firewall-cmd --reload;检查安全组入方向规则。现象 3:HTTPS 访问时,浏览器报
NET::ERR_CERT_COMMON_NAME_INVALID。
原因:certbot 申请证书时-d参数域名和实际访问域名不一致,比如申请了shop.example.com,但用户访问www.shop.example.com。
解决:重新申请,sudo certbot --apache -d shop.example.com -d www.shop.example.com。现象 4:
mod_security启用后,register.php提交总是 403 Forbidden。
原因:CRS 规则误杀,register.php的 POST 数据含password字段,被规则920300(SQL injection)拦截。
解决:临时禁用该规则,在/etc/httpd/modsecurity.d/activated_rules/REQUEST-942-SQLI-ATTACKS.conf中注释掉SecRule行,或加白名单:SecRule REQUEST_URI "@streq /register.php" "id:1001,phase:1,nolog,pass,ctl:ruleRemoveById=920300"。现象 5:
admin/目录被封禁后,admin/index.php也打不开,但它是合法后台。
原因:<Directory "/var/www/html/includes">规则写错了位置,影响了整个/admin/。
解决:规则必须精准定位includes目录,<Directory "/var/www/html/includes">不能写成<Directory "/var/www/html">。
6. 验证与调优:用 3 个 curl 命令,10 分钟内确认 JDShop 是否真可用
部署不是终点,验证才是。别信浏览器刷新,要用curl模拟真实请求链路,覆盖「访客浏览→用户注册→下单支付」全流程。我每次上线前必跑这三步,漏一步,上线后就是 P0 故障。
6.1 第一步:验证静态资源链路——curl -I看 HTTP 头
目标:确认login.css、good.js、img/logo.png全部返回200 OK,且Content-Type正确。
# 测试 CSS curl -I http://shop.example.com/css/login.css # 应返回:HTTP/1.1 200 OK + Content-Type: text/css # 测试 JS curl -I http://shop.example.com/js/good.js # 应返回:HTTP/1.1 200 OK + Content-Type: application/javascript # 测试图片 curl -I http://shop.example.com/img/logo.png # 应返回:HTTP/1.1 200 OK + Content-Type: image/png技巧:
-I只取响应头,不下载内容,秒级完成。如果某项返回404或403,立刻查文件路径和权限;如果Content-Type是text/plain,说明 Apache 没关联 MIME 类型,需在/etc/httpd/conf/httpd.conf中加AddType text/css .css。
6.2 第二步:验证动态页面功能——curl -L跟跳转,抓关键字符串
目标:register.php提交后能跳转到login.php,且返回 HTML 中含欢迎注册字样。
# 模拟注册请求(JDShop 的 register.php 用 POST,字段名是 username/pwd/email) curl -L -X POST "http://shop.example.com/register.php" \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "username=testuser" \ --data-urlencode "pwd=testpass123" \ --data-urlencode "email=test@example.com" \ -s | grep -q "欢迎注册" && echo "✅ 注册成功" || echo "❌ 注册失败"逻辑说明:
-L自动跟随 302 跳转(register.php会header("Location: login.php"););-s静默模式;grep -q静默匹配,成功返回 0。如果失败,用curl -v看详细响应头和 body,找500或Parse error。
6.3 第三步:验证数据库交互——curl+mysql双校验
目标:
本文还有配套的精品资源,点击获取