ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CentOS 7 LAMP环境搭建指南:Apache+PHP+MySQL完整配置与排错

CentOS 7 LAMP环境搭建指南:Apache+PHP+MySQL完整配置与排错 简介一份面向Linux运维初学者与Web环境搭建者的CentOS 7 LAMP环境配置指南聚焦Apache、PHP、MySQL三个核心组件的安装与联动。文档从准备工作讲起覆盖firewalld关闭、iptables端口放行、SELinux禁用等基础设置随后分步说明Apache的安装、httpd.conf常用修改与语法检查以及PHP解析器的部署和Apache处理.php文件的配置方式最后给出MySQL服务启动及整合验证的要点。内容以命令行操作为主线附带配置文件关键片段和验收思路便于按步骤实践。资源为单个PDF文档文件大小955KB目前已有109人学习。对于需要快速搭建Linux动态网站环境、梳理LAMP配置流程的读者而言可直接对照命令完成部署并借助文中的检查与重启方法规避常见配置错误。1. CentOS 7 上把 Apache PHP MySQL 装通一份老 PDF 背后的生产环境刚需接到一个活一台 CentOS 7 老服务器要跑一套很多年前的 PHP 业务系统。系统不换发行版、上容器也不现实只要求在现网把这套 Apache PHP MySQL 搭起来。这个标题看起来像十几年前的老教程但直到今天CentOS 7 的生产环境里依然大量跑着 LAMP——要么是迁移成本太高要么是配套的 PHP 项目只认这套组合。这篇文章就把这套配置从 yum 源选型、服务安装、虚拟主机配置到踩坑排错完整讲透。适合两类人刚接手 CentOS 7 服务器的运维以及要在老环境里重新部署 PHP 项目的开发。读完你能独立装完并且知道 Apache 启动失败、MySQL socket 连不上、PHP 不解析这些问题到底出在哪一层。2. 装 Apache 与 PHPyum 源选型、最小命令和 2.4 的语法坑2.1 先换一个能用的 yum 源CentOS 7 默认源的 PHP 只有 5.4CentOS 7 官方源给出的 httpd 是 2.4.6、PHP 是 5.4这在 2014 年没问题但放到现在跑新项目就是处处报警告。所以第一步不是装包而是把 yum 源整理好。常见做法是先备份自带 repo再换成阿里云镜像源同时装 EPEL 和 Remi 仓库——Remi 把 PHP 按版本拆成了 php74、php80 这类模块装哪个版本由你选默认源里根本没有这个能力。# 备份原始 repo 配置避免换源后想回退连后悔药都没有 mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/CentOS-*.repo /etc/yum.repos.d/backup/ # 用阿里云镜像站的 CentOS 7 repo手工下载到对应位置 curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo yum clean all yum makecache # 装 EPEL 和 Remi 仓库Remi 是装新版 PHP 的前提 yum install -y epel-release yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm这段逻辑有个容易被忽略的点先备份再覆盖换了源以后如果发现公司内网走代理、或者某些内网包只有默认源才有可以随时切回去。Centos-7.repo 里我一般只看 base 和 updates 两个源的 baseurl 是否指向 mirrors.aliyun.com其他源路径错了会直接影响 yum makecache 的完成度。另外如果服务器在内网还要在 /etc/yum.conf 里加上 proxy 配置否则 curl 这步就会卡住。这里给你一个提示如果你维护的机器比较多建议把这个过程写成一条脚本固定好仓库版本别每次手工下载。2.2 Apache 最小安装httpd.conf 里必须先改的两个地方装 Apache 本身不复杂复杂的是装完以后那些“启动失败请检查相关配置”的报错。我一般建议在启动之前就把 httpd.conf 的核心参数改到位而不是等 systemctl start 报错了再回头猜。# 先安装 httpd yum install -y httpd # 把默认的 ServerName 注释去掉改成 localhost 或实际域名 sed -i s/#ServerName www.example.com:80/ServerName localhost:80/ /etc/httpd/conf/httpd.conf # 改完先做语法检查再启动 httpd -t systemctl enable --now httpdServerName 不配只是启动时给你一句 “Could not reliably determine the servers fully qualified domain name” 的警告但如果你后面要做虚拟主机没有 ServerName 的站点会变成默认兜底站访问 IP 时串到第一个 vhost 上去这是最隐蔽的玄学问题之一。httpd -t是apachectl configtest的简写改任何配置之后先跑一遍这条能拦下 80% 的语法类启动失败。接着要看一下内置的默认站点目录配置。CentOS 7 的 httpd.conf 里默认有一个Directory /var/www/html块Apache 2.4 的访问控制语法跟 2.2 完全不同——2.2 时代的Order Deny,Allow写法已经废弃2.4 统一用Require指令。Directory /var/www/html Options Indexes FollowSymLinks AllowOverride All Require all granted /DirectoryRequire all granted是 2.4 的默认授权写法等价于以前的全放开如果你只想让内网访问改成Require ip 192.168.1.0/24就行。AllowOverride All是为了让 .htaccess 生效的如果项目里没有用 .htaccess 做路由改写我建议改成AllowOverride None省掉每次请求都去查目录级别的配置文件。这个也是新手最容易踩的坑拿网上的 2.2 配置直接贴结果站点 403 或者 Apache 起不来。2.3 装 PHP 并让 Apache 认出来mod_php 和 PHP-FPM 怎么选装 PHP 的方式有两条路线取决于你的场景。单机跑一个小站点用 mod_php 模块方式最简单如果计划做多版本 PHP 共存、或者后面要和 Nginx 混用就上 PHP-FPM。用 Remi 源装 PHP 7.4 的命令是这样注意包名前缀带 php74# 通过 remi 源安装 PHP 7.4 及常用扩展 yum install -y php74-php php74-php-mysqlnd php74-php-fpm php74-php-gd php74-php-xml # 配置 php.ini 时区避免 date() 相关函数全部报警告 sed -i s/;date.timezone /date.timezone Asia\/Shanghai/ /etc/opt/remi/php74/php.ini # 启动 php-fpm 并重启 httpd systemctl enable --now php74-php-fpm systemctl restart httpd包名里的 mysqlnd 是 PHP 7.x 的官方 MySQL 驱动老旧的 php-mysql 包已经不再维护如果你在装扩展时看到依赖的是 php-mysqlnd 而不是 php-mysql这是正常现象。php.ini 的时区如果不设后面跑任何用 date() 的项目都会在日志里刷 “It is not safe to rely on the systems timezone settings”这个错不算致命但很烦。如果你不想用 Remi直接yum install -y php php-mysqlnd也可以只是版本会被锁在 5.4。对于老项目这未必是坏事——很多遗留系统还真的只跑得动老版本。但新项目我建议直接接受 PHP 7.4 或 8.0别在 5.4 上给未来的自己挖坑。装完以后验证 Apache 是否认得了 PHP用一条命令就够了httpd -M | grep php输出里有php7_module之类的行说明模块已加载。选 PHP-FPM 模式的注意httpd 默认不会执行 PHP你需要在虚拟主机里加一段 proxy 配置这个放到后面第 4 章结合实际配置讲。这里先把模块方式跑通是最稳的第一步。3. 装 MySQL从 MariaDB 到官方 MySQL 5.7连接方式决定后面省不省心3.1 CentOS 7 的 yum 装出来的“mysql”其实是 MariaDB在 CentOS 7 上直接yum install mysql-server装出来的实际是 MariaDB 5.5这是 CentOS 用 MariaDB 替代 MySQL 之后的结果。如果项目不挑版本、走默认配置就行我推荐就用它因为 yum 替你把依赖和服务脚本全部处理好了安装成本最低。# 安装 MariaDB 服务端和客户端 yum install -y mariadb-server mariadb # 启动并设置开机自启 systemctl enable --now mariadb # 执行初始化安全设置设置 root 密码、去匿名账号 mysql_secure_installationmysql_secure_installation是跑完必做的清理步骤它会让你设置 root 密码、删除匿名用户、移除 test 库。注意翻译一下它默认允许 root 通过 socket 方式以本地身份登录这在 CentOS 上是 MariaDB 的默认行为——如果你后面发现 root 明明设了密码但 PHP 连不上先想 socket 路径再想密码本身。如果你的项目明确要求 MySQL 5.7/8.0那使用 MariaDB 可能会在版本兼容性上翻车特别是用到 JSON 函数、窗口函数这类功能和 MySQL 有差异的语法。这时候就要走官方仓库装 MySQL下面细说。3.2 用官方 yum 仓库装 MySQL 5.7临时密码那一步别跳过MySQL 官方提供了一个 yum 仓库装上它之后yum install mysql-community-server就能拿到真正的 MySQL。我一般用 localinstall 方式安装仓库让 yum 自己解析依赖。# 安装 MySQL 官方 yum 仓库版本号以官方仓库页面为准 yum localinstall -y https://repo.mysql.com/mysql57-community-release-el7-11.noarch.rpm # 安装服务端 yum install -y mysql-community-server # 启动服务 systemctl enable --now mysqld # MySQL 5.7 首次启动自动生成临时 root 密码去 error log 里捞 grep temporary password /var/log/mysqld.log这里有个关键点第一次登录必须用这条临时密码登录后立刻改密码。5.7 默认装了 validate_password 插件对密码强度有要求——你设123456会直接被拒至少要大小写字母加数字和符号的组合。很多教程省略了这一步导致用户后面在“为什么密码对了还是登不上”上浪费大量时间。首次登录改密码的 SQL 语法是这样ALTER USER rootlocalhost IDENTIFIED BY Your_Strong_Pass_2024;3.3 建业务库和专用账号别把 root 直接给 PHP 用数据库启动后下一步是创建业务库和一个专用账号。这样做的好处是即使 PHP 代码被注入漏洞攻击者拿到的也只是一个受限账号而不是整个数据库。-- 创建业务库字符集用 utf8mb4 而不是 utf8 CREATE DATABASE appdb DEFAULT CHARACTER SET utf8mb4; -- 创建专用账号只授权给 appdb 这一个库 CREATE USER appuserlocalhost IDENTIFIED BY App_Pass_2024; GRANT ALL PRIVILEGES ON appdb.* TO appuserlocalhost; FLUSH PRIVILEGES;utf8mb4比utf8多支持四字节字符emoji 和生僻字都能正常存。MySQL 的utf8实际只是 utf8mb3是不完整的 UTF-8这也是存取中文相关数据时乱码的隐藏源头之一。然后给 PHP 一个最小连接测试这一步能确认 PHP、MySQL、网络三层都没有问题?php // 最小连接测试用 PDO 走 TCP 连接 MySQL $dsn mysql:host127.0.0.1;dbnameappdb;port3306;charsetutf8mb4; $user appuser; $pass App_Pass_2024; try { $pdo new PDO($dsn, $user, $pass); $pdo-setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); echo connect ok: . $pdo-query(SELECT VERSION())-fetchColumn(); } catch (PDOException $e) { // 生产环境别直接回显异常信息写日志更安全 error_log($e-getMessage()); echo connect failed; }注意 DSN 里 host 写的是 127.0.0.1这个写法会强制走 TCP 协议如果写hostlocalhostPHP 会尝试通过 Unix socket 连接而 socket 的路径一旦和 mysqld 实际监听的路径不一致就会触发经典报错error 2002 (HY000): cant connect to local MySQL server through socket /tmp/mysql.sock。这个坑到第 5 章会详细展开。这里先把 TCP 方式跑通后面再决定要不要切 socket。4. 把三件套串成站点虚拟主机、PHP-FPM 拆分和防火墙/SELinux 放行4.1 配置一个像样的虚拟主机别把东西直接丢进 /var/www/html很多人配置完 LAMP 就把项目文件直接丢到/var/www/html下面这在小项目上没问题但当你开始跑多个站点、需要各自独立的日志和目录权限时虚拟主机几乎是必须的。在/etc/httpd/conf.d/下新建一个 vhost 配置文件一个文件管一个站点出问题的时候定位范围小很多。VirtualHost *:80 ServerName app.example.com DocumentRoot /var/www/app/public ErrorLog /var/log/httpd/app-error.log CustomLog /var/log/httpd/app-access.log combined Directory /var/www/app/public Options -Indexes FollowSymLinks AllowOverride All Require all granted /Directory /VirtualHost几个参数说清楚Options -Indexes是关闭目录列表避免访问没有 index.php 的目录时整个文件结构被列出来这是生产环境的基本卫生习惯AllowOverride All允许项目里的 .htaccess 生效如果你用的是 Laravel、ThinkPHP 这类框架路由重写经常依赖它——但如果你能在 vhost 里直接写完规则我建议关掉它节省性能。DocumentRoot指向 public 目录是现在 PHP 框架的惯例把入口限制在 public 子目录模型、配置、日志这些文件就不会被 web 直接访问。目录创建和权限这块也有固定做法mkdir -p /var/www/app/public echo ?php phpinfo(); /var/www/app/public/index.php chown -R apache:apache /var/www/appchown给 apache 用户是因为 httpd 进程是以 apache 身份运行的如果目录属主是 rootPHP 写入文件时会报权限不足。很多“图片传不上去”“日志写不了”的问题根子就是这里属主不对。4.2 走 PHP-FPM 而不是 mod_php什么时候值得切第 2 章提到过两种 PHP 运行模式。mod_php 是作为 Apache 模块加载的简单直接PHP-FPM 是独立进程池PHP 进程由 FPM 管理不再依赖 Apache 的生命周期。切到 FPM 模式后PHP 的并发配置更灵活跑多版本 PHP 也不会互相干扰而且重启 PHP 不用动 Apache。在 Apache 2.4 里接 PHP-FPM 的常见做法是用mod_proxy_fcgi# 在 vhost 里加一段所有 .php 请求转发给 php-fpm 的 socket ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/var/run/php74-php-fpm.sock|fcgi://127.0.0.1:9000这条配置的写法很讲究unix:后面是 php-fpm 的 socket 文件路径这个路径必须和你 php-fpm 配置文件里的listen参数一致。如果你在/etc/opt/remi/php74/php-fpm.d/www.conf里看到listen /var/run/php74-php-fpm.sock那这里就填这个路径如果改成了listen 127.0.0.1:9000那配置应该写成fcgi://127.0.0.1:9000。前后不对应会出现 503 或者 500 错误看日志时注意区分。给一个最直接的选型建议如果这台机器就跑一个站点、PHP 版本固定mod_php 最省心如果未来要同时跑两套不同 PHP 版本的项目、或者你正在用源码包编译 PHP 扩展做调试PHP-FPM 更合适——因为 FPM 模式下单独重启 PHP 不会中断 Apache 的连接调试成本低很多。4.3 防火墙和 SELinux两层放行缺一不可HTTP 服务装完却访问不了第一步查的不是 httpd 配置而是防火墙。CentOS 7 默认用了 firewalld80 端口默认不放行。# 放行 http 服务并重载防火墙 firewall-cmd --permanent --add-servicehttp firewall-cmd --reload # 验证端口已放行 firewall-cmd --list-services防火墙看着没问题之后还有一个更隐蔽的拦路虎SELinux。CentOS 7 默认是 Enforcing 模式它会拦 Apache 进程的网络连接。最常见的表现是网页能打开、PHP 代码能跑但连接数据库时报权限错误命令行里用同一个账号连数据库却是正常的。# 查看当前 SELinux 状态 getenforce # 打开 httpd 访问数据库的布尔值-P 让重启后依然生效 setsebool -P httpd_can_network_connect_db on # 如果 PHP 还需要连 Redis 等外部网络服务再放开通用网络连接 setsebool -P httpd_can_network_connect on很多人为了省事直接setenforce 0甚至改配置文件关掉 SELinux这种操作在公网环境的服务器上我不建议。CentOS 7 默认开启的这套访问控制虽然平时不出声但真出事的时候能帮你挡不少东西。正确做法是只放开需要的布尔值。顺带提一个业务接口场景如果你的站点是给前端提供 JSON 接口的PHP 里把数组json_encode输出给前端的fetch或axios用这是常规操作。涉及跨域时能用 CORS 响应头解决的问题不要用 jsonp——jsonp 是动态插入 script 的方式在安全性上比 CORS 脆弱得多特别是不该出现在需要登录态的接口上。5. 避坑实录LAMP 环境下最常翻车的 5 个症状与对应解法5.1 Apache 启动失败、请检查相关配置先分清是语法错误还是端口占用现象systemctl start httpd报Job for httpd.service failed旧教程里就一句“请检查相关配置”没有更多信息。原因最常见就两种——httpd.conf 语法错误或者 80 端口被 Nginx、别的服务占掉了。还有一种情况是 httpd.conf 里的Listen 80写重复了也会直接起不来。解决步骤# 第一步永远先跑语法检查别去看日志 httpd -t # 语法没问题再启动如果还失败看 systemd 日志 systemctl start httpd journalctl -u httpd -n 30 --no-pager # 如果提示端口被占用用 ss 找到占用进程 ss -lntp | grep :80httpd -t只检查配置文件语法不检查端口。journalctl -u httpd是 systemd 时代的日志读法比去翻/var/log/httpd/error_log更及时、更全。ss输出里最后一列就是占用端口的进程名和 PID看到是 Nginx 占着 80 就想办法协调端口别直接 kill。5.2 MySQL 5.1 启动失败、请检查相关配置数据目录权限和 my.cnf 的 socket 路径现象启动 MySQL/MariaDB 时节点失败错误提示是笼统的 “请检查相关配置”具体原因被日志挡在后台。原因多数是/var/lib/mysql数据目录的属主不是 mysql或者/etc/my.cnf里手写了错误的 socket 路径。CentOS 7 里 MariaDB 和 MySQL 是两套体系按老经验去改 my.cnf 很容易写错。解决步骤# 先看错误日志别瞎猜 tail -50 /var/log/mysql/mysqld.log 2/dev/null || tail -50 /var/log/mysqld.log # 数据目录属主不对就改这是最常见的启动失败原因 chown -R mysql:mysql /var/lib/mysql # 确认 my.cnf 里的 socket 路径客户端、服务端、PHP 三处必须一致 grep -n socket /etc/my.cnf这里要特别注意MySQL 官方源和 MariaDB 的日志文件路径是不一样找不到日志就先去/etc/my.cnf看log-error配置指向哪。改完属主之后重启如果还失败再回去看日志——日志排错永远是第一选择比在网上搜报错片段快得多。5.3 error 2002: cant connect to local MySQL server through socketlocalhost 走 socket、127.0.0.1 走 TCP现象PHP 连接数据库时报error 2002 (HY000): cant connect to local MySQL server through socket /tmp/mysql.sock命令行用 root 却连得上。原因PHP 的 DSN 里写的是hostlocalhostPHP 会自然选择用 socket 文件连接但 mysqld 实际监听的 socket 路径不在/tmp/mysql.sock两边对不上。解决思路先确认 mysqld 在跑再找出 socket 真实路径然后把 PHP 侧改成对应的连接方式。# 确认 mysqld 进程和 socket 文件位置 pgrep -x mysqld find / -name *.sock 2/dev/null | grep -i mysql # PHP 侧最省事的做法强制走 TCP绕开 socket 路径问题 $dsn mysql:host127.0.0.1;port3306;dbnameappdb;charsetutf8mb4;localhost走 socket、127.0.0.1走 TCP 是 PHP/MySQL 交互里翻车频率最高的经典盲区。如果项目里有的地方写 localhost、有的地方写 127.0.0.1线上就会出现“这台机器能连那台不能连”的怪现象。代码里的host统一用 127.0.0.1 指定port能让问题少一大半。如果对性能有要求再考虑走 socket——本地 socket 连接因为省掉 TCP 协议栈的开销延迟确实能低一些但前提是 socket 路径统一。5.4 访问 PHP 文件变成下载或源码被打印httpd 没找到 PHP 处理器现象浏览器访问.php文件要么弹下载框要么直接把 PHP 源码文本打在页面上而不是执行。原因装完 PHP 后没有重启 httpd或者装的是 PHP-FPM 模式但虚拟主机里没加ProxyPassMatch转发规则。Apache 收到请求后不知道把.php交给谁解析就当成普通静态文件返回了。解决步骤# 确认 PHP 模块是否被 httpd 加载 httpd -M | grep php # mod_php 模式下输出里应有 php7_module 或对应版本行 # 没有的话重装 php 与 httpd 兼容的版本 # 命令行先验证 PHP 本身没问题 php -r echo ok\n; # 最后重启 httpd 生效 systemctl restart httpd如果命令行能输出 ok 但 web 访问还是下载问题就锁定在 httpd 和 PHP 的集成上。常见排查法看目录里有没有.htaccess配置了奇怪的处理规则再看 vhost 里的 Directory 块是不是把 php 文件的执行权限禁掉了。5.5 SELinux Enforcing 下 PHP 连不上 MySQL但命令行能连现象网页上打开数据库相关页面报权限错误命令行里用同一个账号连数据库却完全正常。原因CentOS 7 默认 SELinux 是 Enforcinghttpd 进程出站的数据库连接被 SELinux 策略拦截。命令行操作是用户态不经过 httpd 域所以不受限。解决步骤# 确认这不是玄学直接查布尔值 getsebool -a | grep httpd_can_network # 打开 httpd 访问数据库的开关加 -P 让配置重启后保留 setsebool -P httpd_can_network_connect_db on # 如果项目还连 Redis、Memcached 等外部服务 setsebool -P httpd_can_network_connect on这一条是 CentOS 6 迁移到 7 之后最容易踩的隐性差异CentOS 6 时代很多装机教程第一步就关 SELinux到了 7 默认开启老配置原封不动搬过来就失灵。建议每次都先用getsebool -a看看现状再决定要不要开开关不要盲目 setenforce 0 关掉整个 SELinux。6. 验证与收尾从 phpinfo 探针到压测把配置钉在纸上整套配置完成后别急着交工。先做一条链路的完整验证再做一个最小压测把性能基线留在手里后续出问题才有对比依据。先跑最基础的验证命令# 看 HTTP 响应头确认返回 200 curl -I http://127.0.0.1/ # 确认 PHP 在 web 层能执行而不是被当静态文件返回 curl http://127.0.0.1/index.php # 看 PHP 已加载的模块确认 mysqlnd、gd 这些都在 php -m | grep -E pdo|mysqlnd|gd然后做一个顺手的最小压测用 Apache 自带的 ab 工具yum install -y httpd-tools ab -n 100 -c 10 http://127.0.0.1/index.php压测主要看两个数Requests per second和Failed requests。前者是吞吐量基线后者是 0 才合格。如果吞吐量很低而且服务器 CPU 没跑满八成是 PHP-FPM 进程数不够去php-fpm.d/www.conf里调pm.max_children和pm.max_requests这两个参数决定 FPM 能同时撑多少 PHP 进程、每个进程扛多少请求后自动回收。我自己的习惯是每改一个配置先cp一份带日期的备份再跑语法检查最后才重启服务。比如改 httpd.conf 之前先cp httpd.conf httpd.conf.bak-20240601改完跑httpd -t确认没问题再systemctl restart httpd。这个习惯救过我很多次配置文件被你改坏的时候一条mv命令就能回到上一个可用状态。这套 LAMP 环境装完后把 yum 源选型、PHP 版本、数据库账号、selinux 布尔值这几项记到文档里下次扩容直接照抄比临时回忆靠谱得多。希望帮到你。本文还有配套的精品资源点击获取
返回列表