ARTICLE DETAIL

资讯详情

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

LNMP环境搭建详解:yum与源码编译双路线实战指南

LNMP环境搭建详解:yum与源码编译双路线实战指南 LNMP这套组合在服务器领域摸爬滚打过的朋友应该都不陌生。Linux Nginx MariaDB/MySQL PHP几乎撑起了全网半壁江山的动态站点。不管是个人博客、企业官网还是跑WordPress、ThinkPHP这类框架应用LNMP都是最经典、最常用的底座。这篇文章我不打算空谈概念直接带你走一遍完整实操。我会以CentOS 7为例同时覆盖yum安装和源码编译安装两条路线。为什么两条都要讲因为实际工作里两种场景都太常见了yum装东西快、省事适合测试环境和业务迭代速度快的场景编译安装则胜在可控性强、版本灵活、能针对服务器CPU做优化生产环境里很多老玩家还是倾向于自己编译。我会把两条路的每一步命令、每个参数的作用、可能踩的坑都摊开讲清楚。这篇内容适合刚接触Linux服务器的小白也适合想回头补补细节的运维老手。1. 环境准备与整体方案选型1.1 系统基础配置与网络准备动手之前先把底子打好。我用的是CentOS 7.92009版内核版本3.10.0-1160这是这个系列的最终版本也是最稳定的一个。拿到一台全新服务器后第一件事不是急着装东西而是确认三件事网络通不通、仓库能不能用、时间对不对。检查网络连通性最简单的方式就是ping一下外网地址ping -c 4 www.baidu.com如果返回了正常的ICMP回包说明基础网络没问题。接着要看DNS解析是否正常很多刚装完的系统会碰到“能ping通IP但解析不了域名”的怪问题通常是/etc/resolv.conf里没配置DNS服务器导致的cat /etc/resolv.conf # 如果为空或只有内网DNS建议加上公共DNS echo nameserver 8.8.8.8 /etc/resolv.conf echo nameserver 223.5.5.5 /etc/resolv.conf这里有个细节值得注意在CentOS 7上直接改/etc/resolv.conf有可能会被NetworkManager或dhclient覆盖掉尤其是重启网络服务之后。如果发现改完又被重置就编辑/etc/sysconfig/network-scripts/ifcfg-eth0网卡名按实际来在文件里加上DNS配置然后重启网络服务才稳妥。再看一下系统的版本和位数确认自己手里是CentOS 7而不是其他衍生版本cat /etc/redhat-release uname -a架构信息也有必要看一眼因为后面编译安装时要根据CPU架构选择对应的优化参数。绝大多数云服务器都是x86_64个别ARM架构的机器在编译时会有区别提前确认能少走弯路。1.2 yum安装与编译安装的取舍逻辑在正式动手前我建议你先想清楚一个问题这条路到底选yum还是选编译这不是谁优谁劣的绝对判断题而是取决于你的实际场景。yum安装的适用场景yum的最大优势是“快”和“省心”依赖关系自动处理。装一个PHP它会自动帮你把libxml2、curl、gd库这些关联的扩展包全部拉下来不会出现“装A缺B装B缺C”的连环依赖地狱卸载干净。yum remove会把关联的二进制文件和依赖系统包一并清理不会在系统里留下七零八落的残骸升级方便。以后要更新补丁或版本一行yum update搞定但yum的短板也很明显官方源里的软件版本普遍偏老。以PHP为例CentOS 7官方源默认的PHP版本是5.4这是2012年的老家伙放到今天连基本的兼容性都是问题更别提PHP 7之后的性能飞跃了。所以用yum装PHP时往往需要额外配置EPEL和Remi仓库绕一圈才能装到PHP 7.x。源码编译安装的适用场景编译安装的核心优势在于四个字自定义、可控。你在./configure阶段就能决定要启用哪些特性、禁用哪些模块像PHP的--with-openssl、--enable-fpm都是这一步指定的安装路径完全自己定比如我就习惯统一放到/usr/local/下面管理和备份都很顺手可以针对当前机器的CPU架构做优化编译把指令集特性全部发挥出来编译安装的代价是等待时间较长在低配机器上二进制包编译几分钟到十几分钟都很正常。此外如果对编译过程不熟中途报错排查起来会很吃力这是对新手最不友好的地方。我的建议很简单如果你只是本地测试、学习练手不想浪费时间优先yum安装如果你要在生产环境部署、追求版本自由或者需要深度定制那编译安装更靠谱。但不论你选了哪条路这篇文章我都会把两条路完整走一遍你可以一条路走到底也可以作为互补参考。1.3 提前关闭或配置的操作项安装LNMP之前还有两个系统组件需要处理一个是SELinux一个是系统防火墙。SELinux安全增强型Linux是CentOS 7默认开启的强制访问控制模块。它的设计初衷很好保护系统不被异常进程越权操作。但在LNMP实际运行时SELinux经常会拦截Nginx对PHP-FPM的socket访问导致明明一切配置都正确页面却显示502错误。排查起来相当绕人。我的做法是测试环境直接关闭SELinux生产环境如果安全要求高就按需配置布尔值而不是简单粗暴地禁用# 查看当前SELinux状态 getenforce # 临时关闭重启失效 setenforce 0 # 永久关闭编辑/etc/selinux/config sed -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config防火墙这边同样需要处理。CentOS 7默认用的是firewalld最直接的验证方式就是装完Nginx后用浏览器访问IP如果打不开八成就是防火墙拦了80端口。开通端口的方式firewall-cmd --permanent --add-port80/tcp firewall-cmd --permanent --add-port443/tcp firewall-cmd --reload这里顺带提醒一句如果你用的是云服务器阿里云、腾讯云等光在系统里放行还不够还需要到云控制台的安全组规则里放行对应端口。这个坑我踩了不止一次每次都以为代码问题结果一看安全组根本没开端口。2. Nginx安装两条路分别怎么走2.1 通过yum快速安装NginxNginx在CentOS 7官方源里其实就有但版本相对保守。为了能装到新一点的版本我一般会先安装EPELExtra Packages for Enterprise Linux仓库。EPEL是Fedora社区为RHEL系发行版维护的一份高质量扩展软件包集合里边的Nginx版本要比官方源新不少# 安装EPEL仓库 yum install -y epel-release # 更新缓存并安装Nginx yum install -y nginx安装完成之后先不要急着启动先看一下版本和编译参数nginx -v nginx -Vnginx -V输出的信息里有--add-module、--with-http_ssl_module这些参数能帮你确认Nginx已经编译进来了哪些功能模块。比如需要HTTPS支持时就得确认有--with-http_ssl_module。EPEL仓库里的Nginx默认都带上了常用模块日常使用足够。接着启动服务并设置开机自启systemctl start nginx systemctl enable nginx启动完成后检查一下状态systemctl status nginx看到active (running)就说明没问题了。此时在浏览器里输入你的服务器IP地址如果能看到Nginx的默认欢迎页说明Web服务已经跑起来了。有几点细节要给到大家Nginx默认的网站根目录是/usr/share/nginx/html但实际生产环境很少直接用它一般会在数据盘或独立目录下创建站点目录默认配置文件在/etc/nginx/nginx.conf它通过include指令加载/etc/nginx/conf.d/目录下所有.conf文件。实际配置站点时建议在conf.d下新建文件而不是改动主配置EPEL仓库的nginx启动用户默认是nginx如果想要改成www或其他用户需要手动改配置2.2 源码编译安装Nginx如果你选择编译安装那就要多花一点功夫但也意味着更多的控制权。Nginx本身依赖PCRE正则表达式库、zlib压缩库和OpenSSL加密库编译前需要先把这些依赖准备好。先下载Nginx源码。我会在官网找最新的稳定版本以Nginx 1.24.0为例cd /usr/local/src wget https://nginx.org/download/nginx-1.24.0.tar.gz tar -zxvf nginx-1.24.0.tar.gz下载完源码包之后先安装编译工具链和依赖库yum install -y gcc gcc-c make pcre-devel zlib-devel openssl-devel这批依赖里gcc和gcc-c是编译必不可少的编译器pcre-devel等-devel包是开发头文件。很多人编译时碰到“找不到PCRE”的报错就是因为只装了pcre没装pcre-devel。接下来是重点./configure配置编译参数。这是Nginx编译安装中最核心的一步参数直接决定了编译出来的二进制具备哪些功能cd nginx-1.24.0 ./configure \ --prefix/usr/local/nginx \ --usernginx \ --groupnginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_realip_module \ --with-http_stub_status_module \ --with-pcre说下这几个关键参数的含义--prefix/usr/local/nginx安装目录Nginx的二进制文件、配置文件、日志文件都会放在这个目录下--usernginx --groupnginx指定Nginx工作进程以哪个用户身份运行出于安全考虑绝不能以root身份跑Nginx--with-http_ssl_module启用HTTPS支持--with-http_v2_module启用HTTP/2协议支持对网站访问速度有明显提升--with-http_stub_status_module提供Nginx运行状态监控页面配置完成后就可以编译和安装了make make install这里要特别提醒make之后如果报错不要急着重来先看清楚错误信息。绝大多数情况是缺了某个依赖安装后重新make就行。只有当改动过configure参数时才需要先make clean再重新configure。编译安装完成后Nginx的目录结构是这样的二进制文件/usr/local/nginx/sbin/nginx配置文件/usr/local/nginx/conf/nginx.conf默认网站目录/usr/local/nginx/html日志文件/usr/local/nginx/logs/启动方式和yum装的不太一样因为不是通过systemd管理的/usr/local/nginx/sbin/nginx停止服务/usr/local/nginx/sbin/nginx -s stop重新加载配置平滑重启不中断服务/usr/local/nginx/sbin/nginx -s reload如果你希望编译安装的Nginx也能用systemctl管理那就需要手动写一个systemd服务文件。这个步骤看似多余实际管理中却特别有用这里直接提供模板# /etc/systemd/system/nginx.service [Unit] Descriptionnginx - high performance web server Afternetwork.target [Service] Typeforking PIDFile/usr/local/nginx/logs/nginx.pid ExecStartPre/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf ExecStart/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf ExecReload/usr/local/nginx/sbin/nginx -s reload ExecStop/usr/local/nginx/sbin/nginx -s stop PrivateTmptrue [Install] WantedBymulti-user.target保存文件后执行systemctl daemon-reload systemctl start nginx systemctl enable nginx这样编译安装的Nginx就纳入了systemd管理后面的操作和yum安装的版本保持一致。2.3 两条路装出来的Nginx有什么区别很多朋友会问两种方式装出来的Nginx差别到底有多大这里把关键差异整理成一张表你一看就明白对比项yum安装源码编译安装版本EPEL仓库版本通常略旧官网最新稳定版自由选择安装路径/etc/nginx、/usr/sbin/nginx/usr/local/nginx路径自定义模块扩展默认模块不能追加configure阶段自定义可加第三方模块启动管理systemctl直接管理需手写service文件参照上文后续升级yum update nginx一行搞定需重新下载源码、重新编译适用场景快速部署、测试、对版本不敏感生产环境、功能定制、性能优化我个人的实践感受是yum安装省心适合大部分中小站点编译安装更适合需要接入第三方模块比如nginx-module-vts、headers-more或对性能有极端要求的场景。技术选型没有标准答案适合自己业务的就是最优解。3. 数据库安装MariaDB与MySQL的选型与部署3.1 为什么CentOS 7默认推MariaDB提LNMP里的M早几年大家默认是MySQL但现在的CentOS 7系统仓库直接内嵌的是MariaDB。MariaDB是MySQL的一个分支版本由MySQL的创始人Monty Widenius主导开发在MySQL被Oracle收购后另起炉灶。它保持了对MySQL协议和API的高度兼容同时提供了更多的存储引擎和性能优化项。对于绝大多数应用来说MariaDB和MySQL可以无缝切换。选择数据库前先明确一件事你的应用是否对某个特定数据库版本有硬性要求比如某些老旧的PHP项目依赖MySQL 5.6的特定行为而新版MariaDB未必完全兼容。这类场景建议直接上MySQL官方提供的仓库。大多数情况下MariaDB足以满足日常需求。3.2 yum安装MariaDB推荐如果你选yum路线安装过程比我预想的还要简单CentOS 7官方源里已经内置了MariaDB 5.5版本。但说实话5.5已经是老古董了安全性不支持高版本的功能比如窗口函数这些。如果希望安装更高版本的MariaDB需要手动添加MariaDB官方仓库。不过对于入门和小型业务官方源的5.5先用起来完全是够的。这里把官方源安装方式写全yum install -y mariadb-server mariadb依赖包会自动解决装完之后启动并设置自启systemctl start mariadb systemctl enable mariadbMariaDB安装完成后默认的安全配置是比较宽松的root用户没有密码任何本地用户都能以root身份登录。这时候必须马上执行安全初始化脚本mysql_secure_installation这个脚本会依次引导你完成几件事设置root密码、删除匿名用户、禁止root远程登录、删除测试数据库、刷新权限表。我建议全部选yes尤其要强调禁止root远程登录这一项生产环境如果开放了root远程权限等于把数据库裸奔在公网上。设置好密码之后验证一下能不能正常登录mysql -uroot -p输入刚才设置的密码能看到Welcome to the MariaDB monitor.的提示就说明安装成功了。有一点要注意MariaDB默认配置的字符集是latin1如果不改存中文很容易变乱码。建议修改配置文件/etc/my.cnf在[mysqld]段中添加[mysqld] character-set-serverutf8mb4 collation-serverutf8mb4_unicode_ci然后重启MariaDB让配置生效systemctl restart mariadb登录后执行以下SQL确认字符集已生效SHOW VARIABLES LIKE character_set%;看到character_set_server的值是utf8mb4就对了。3.3 源码编译安装MariaDB/MySQL源码编译数据库难度要比Nginx高一个档次。它依赖cmake工具链编译时间也更长。如果你不是特别需要自定义数据库功能我不太建议走这条路但对想深入了解数据库安装原理的人来说这个过程很有价值。先装工具链yum install -y cmake ncurses-devel bison gcc gcc-c下载源码包。这里以MariaDB 10.6版本为例cd /usr/local/src wget https://archive.mariadb.org/mariadb-10.6.12/source/mariadb-10.6.12.tar.gz tar -zxvf mariadb-10.6.12.tar.gz源码包解压之后创建一个专门用来运行数据库的系统用户groupadd mysql useradd -g mysql -s /sbin/nologin mysql使用/sbin/nologin作为登录shell是为了防止有人通过该账号直接登录服务器属于安全加固的标准做法。接下来是cmake配置阶段。这一步要和configure对应起来理解cmake在数据库编译里起的作用跟configure在Nginx编译里一样cd mariadb-10.6.12 cmake . \ -DCMAKE_INSTALL_PREFIX/usr/local/mariadb \ -DMYSQL_DATADIR/data/mysql \ -DSYSCONFDIR/etc \ -DMYSQL_USERmysql \ -DWITH_INNOBASE_STORAGE_ENGINE1 \ -DWITH_ARCHIVE_STORAGE_ENGINE1 \ -DWITH_BLACKHOLE_STORAGE_ENGINE1 \ -DENABLED_LOCAL_INFILE1 \ -DDEFAULT_CHARSETutf8mb4 \ -DDEFAULT_COLLATIONutf8mb4_unicode_ci \ -DWITH_READLINE1逐个解释一下重点参数-DCMAKE_INSTALL_PREFIX安装路径同Nginx的--prefix-DMYSQL_DATADIR数据库数据文件的存放目录建议单独放进数据盘方便备份-DDEFAULT_CHARSETutf8mb4默认字符集设为UTF-8现在基本不会有人用latin1-DWITH_READLINE1启用命令行历史记录和补全功能操作时方便很多cmake执行无误后就是真正的编译环节了make -j$(nproc) make install-j$(nproc)这个参数很关键nproc能自动获取CPU核心数然后开启对应数量的并行编译任务。比如8核服务器就是make -j8这能极大缩短编译时间。编译完之后初始化数据目录cd /usr/local/mariadb scripts/mysql_install_db --usermysql --basedir/usr/local/mariadb --datadir/data/mysql拷贝配置文件并启动服务cp support-files/my-medium.cnf /etc/my.cnf cp support-files/mysql.server /etc/init.d/mysql chmod x /etc/init.d/mysql最后启动数据库并设置root密码/etc/init.d/mysql start /usr/local/mariadb/bin/mysqladmin -u root password YourNewPassword值得强调的是源码编译数据库整个流程涉及的坑比Nginx多得多尤其是cmake阶段对依赖版本的敏感度很高比如系统里gcc版本太旧会导致编译报错。新手如果只是为了快速跑通业务我建议优先考虑yum安装。3.4 数据库选择与版本兼容性建议数据库选型方面我给几组实用性建议直接拿走就能用跑WordPress用yum装的MariaDB可以轻松跑起来不需要特意的性能调优跑大型电商应用、有复杂查询建议选MySQL 8.0版本其优化器能力明显优于老版本做数据分析、需要窗口函数MariaDB 10.2以上或MySQL 8.0都很合适老项目维护先确认项目依赖的SQL语法版本不要盲目升库版本兼容性这一点很多人会忽略。比如PHP 5.4时代的代码连接MySQL的方式是用mysql_connect()函数而PHP 7之后的版本彻底移除了这个函数换成了mysqli_connect()或PDO。如果你拿新数据库去对接老PHP项目很可能直接白屏。所以在选版本前先确认你PHP应用里用的到底是哪一类连接方式。4. PHP安装与PHP-FPM配置4.1 yum安装PHP及常用扩展PHP是整个LNMP链条里配置最灵活、也最容易出问题的一个环节。CentOS 7官方源的PHP版本是5.4实在太老我在这里强烈建议添加Remi仓库来安装新版PHP。Remi是社区维护的PHP版本仓库提供了PHP 5.4到8.x的多种版本切换方便是RHEL系服务器上安装PHP的主流方案.先安装EPEL再做Remi仓库的引入yum install -y epel-release # 安装Remi仓库 rpm -Uvh https://rpms.remirepo.net/enterprise/remi-release-7.rpm装好仓库后查看有哪些PHP版本可用yum list available php*默认情况下Remi仓库的PHP版本可能不是你想要的这时候需要用yum-config-manager工具来启用对应版本的仓库。比如要启用PHP 7.4yum install -y yum-utils yum-config-manager --enable remi-php74然后在命令行输入yum install php就能装到7.4版本了。如果你需要的是PHP 8.0就把remi-php74换成remi-php80。接下来安装PHP主程序和常用扩展yum install -y php php-fpm php-mysqlnd php-gd php-xml php-mbstring php-json php-curl php-zip这些扩展的作用分别是php-mysqlndPHP连接MariaDB/MySQL的驱动新版替代了老的php-mysqlphp-gd图像处理库图片缩略图、验证码生成都要靠它php-xmlXML解析很多框架的依赖项php-mbstring多字节字符串处理处理中文场景必备php-curlcURL库用于发起HTTP请求php-zipZIP压缩包处理Composer安装依赖时需要装完后验证PHP版本php -v能正确输出版本号说明PHP已经安装完毕。接下来启动PHP-FPM并设置自启systemctl start php-fpm systemctl enable php-fpm这里有个小细节PHP-FPM是FastCGI进程管理器它和Nginx是两个独立进程动态请求通过它们之间的socket通信来完成。默认配置里PHP-FPM监听的可能是127.0.0.1:9000也可能是一个Unix socket文件具体路径需要查看/etc/php-fpm.d/www.conf。查看监听方式grep -E listen /etc/php-fpm.d/www.conf两种方式各有优劣TCP socket127.0.0.1:9000配置更通用跨机器通信也方便Unix socket比如/run/php-fpm/www.sock走的是文件系统少了网络协议栈的开销本机通信性能更好。如果你的Nginx和PHP-FPM在同一台机器上我建议用Unix socket方式。4.2 源码编译安装PHP编译PHP比编译Nginx更复杂一些依赖项更多。老规矩先把基础依赖装齐yum install -y gcc gcc-c make libxml2-devel openssl-devel curl-devel libjpeg-devel libpng-devel freetype-devel下载PHP源码包。以PHP 7.4.33为例这是PHP 7.4系列的最终版本稳定性和兼容性都很好cd /usr/local/src wget https://www.php.net/distributions/php-7.4.33.tar.gz tar -zxvf php-7.4.33.tar.gz然后进入解压目录执行configure配置cd php-7.4.33 ./configure \ --prefix/usr/local/php \ --with-config-file-path/usr/local/php/etc \ --enable-fpm \ --with-fpm-usernginx \ --with-fpm-groupnginx \ --enable-mysqlnd \ --with-mysqlimysqlnd \ --with-pdo-mysqlmysqlnd \ --with-mysql-sock/var/lib/mysql/mysql.sock \ --with-gd \ --with-png-dir \ --with-jpeg-dir \ --with-freetype-dir \ --enable-gd-native-ttf \ --with-openssl \ --with-curl \ --enable-mbstring \ --enable-xml \ --enable-session \ --enable-json \ --enable-zip这些参数里有几个必须认真解释一下--enable-fpm启用PHP-FPM功能这是Nginx与PHP通信的桥梁必须开启--with-fpm-usernginx --with-fpm-groupnginx设置PHP-FPM运行用户为nginx保证PHP进程和Nginx进程权限一致避免文件权限问题--with-mysqlimysqlnd --with-pdo-mysqlmysqlnd指定使用mysqlnd驱动。mysqlnd是PHP官方维护的MySQL驱动性能优秀和数据库交互的关键依赖--with-openssl启用OpenSSL扩展是Composer、HTTPS等场景的硬性要求--enable-fpm之后的其它扩展项按需选择不需要全部启用configure通过后编译安装make -j$(nproc) make install编译PHP的时间会比Nginx长不少在2核4G的机器上PHP 7.4大概需要10-20分钟左右属正常现象。安装完成后还需要手动初始化配置文件。PHP的配置分成两份php.ini和php-fpm.conf分别负责PHP运行参数和进程调优参数# 复制PHP主配置文件 cp php.ini-production /usr/local/php/etc/php.ini # 复制PHP-FPM配置文件 cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf # 复制PHP-FPM的池配置文件 cp /usr/local/php/etc/php-fpm.d/www.conf.default /usr/local/php/etc/php-fpm.d/www.confphp.ini-production是官方的生产环境推荐配置默认开启了更严格的安全设置比如禁用危险函数、默认隐藏PHP版本号等直接使用即可。启动PHP-FPM/usr/local/php/sbin/php-fpm验证进程是否正常启动ps -ef | grep php-fpm能看到php-fpm: master process和多个php-fpm: pool www进程说明PHP-FPM已经跑起来了。编译安装的PHP同样建议加入systemd管理service文件模板如下# /etc/systemd/system/php-fpm.service [Unit] DescriptionPHP FastCGI Process Manager Afternetwork.target [Service] Typeforking PIDFile/usr/local/php/var/run/php-fpm.pid ExecStart/usr/local/php/sbin/php-fpm ExecReload/bin/kill -USR2 $MAINPID PrivateTmptrue [Install] WantedBymulti-user.target4.3 php.ini和PHP-FPM的优化细节安装完PHP只是第一步真正让PHP跑得又快又稳的是配置调优。这里挑几个直接影响实际性能的参数重点说。php.ini中需要关注的参数; 关闭危险函数生产环境建议开启 disable_functions passthru,exec,system,chroot,chgrp,chown,shell_exec,proc_open,popen ; 设置上传文件最大尺寸根据业务需求调整 upload_max_filesize 20M ; 设置POST请求的最大数据量必须比upload_max_filesize大否则大文件上传会出错 post_max_size 25M ; 脚本最大执行时间单位秒 max_execution_time 300 ; 脚本可以占用的最大内存 memory_limit 128M ; 时区设置不设置会告警 date.timezone Asia/Shanghai这几个参数是日常最常碰到的。比如上传图片大小超限优先检查upload_max_filesize如果post_max_size比upload_max_filesize小大概率会上传失败脚本执行超时则检查max_execution_time。PHP-FPM的进程池配置PHP-FPM的进程管理策略在/etc/php-fpm.d/www.confyum安装或/usr/local/php/etc/php-fpm.d/www.conf编译安装中配置核心是pm和几个相关参数; 进程管理方式可选static、dynamic、ondemand pm dynamic ; 子进程最大数量根据服务器内存大小调整 pm.max_children 50 ; 动态模式下空闲时保持的子进程数 pm.start_servers 5 pm.min_spare_servers 5 pm.max_spare_servers 35三者的区别static固定创建指定数量的子进程。资源占用稳定但流量波动大时容易浪费或不足dynamic根据当前负载动态调整子进程数灵活性最好大多数场景推荐ondemand有请求时才创建子进程空闲时全部回收最省内存但响应速度稍慢pm.max_children的计算方法假设服务器内存为4G每个PHP-FPM子进程约占30-50M内存取决于业务复杂度那么max_children可以设置在50-80之间。但具体数值更要看你的应用实际占内存的多少老项目常会遇到子进程数超过上限导致内存溢出的问题调参时要结合监控数据来。改完配置后都需要重启PHP-FPM才生效systemctl restart php-fpm # yum安装方式 # 或 kill -USR2 $(cat /usr/local/php/var/run/php-fpm.pid) # 编译安装平滑重载5. 整合LNMPNginx配置与动态站点部署5.1 创建站点目录与测试文件到这里LNMP的三个核心组件都已经各就各位了。但它们目前还是各自独立的进程互相之间还没有打通。接下来要做的就是通过Nginx的配置把它们粘合成一个整体。首先规划站点目录。我的习惯是统一放在/data/wwwroot/下面以域名分目录方便后续多站点管理mkdir -p /data/wwwroot/blog.test.com echo h1LNMP Test Page/h1 /data/wwwroot/blog.test.com/index.html这里顺带说一个很实用的习惯项目文件不要放在root用户目录下。我自己常用的做法是创建一个www用户并将站点目录授权给它useradd -M -s /sbin/nologin www chown -R www:www /data/wwwroot5.2 编写Nginx站点配置文件yum安装的Nginx站点配置通常放在/etc/nginx/conf.d/下编译安装的需要在/usr/local/nginx/conf/下手动创建站点目录。我以yum安装路径为例新建blog.test.com.confserver { listen 80; server_name blog.test.com; root /data/wwwroot/blog.test.com; index index.php index.html index.htm; # 处理PHP请求的核心配置 location ~ \.php$ { fastcgi_pass unix:/run/php-fpm/www.sock; # 如果PHP-FPM监听的是TCP端口则用下面这行 # fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } # 静态文件缓存减轻后端压力 location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 7d; access_log off; } # 隐藏隐藏文件防止敏感信息泄露 location ~ /\. { deny all; } }这段配置有几个关键点root指定了站点文件所在的根目录location ~ \.php$用正则匹配以.php结尾的请求然后把请求转发给PHP-FPM处理fastcgi_pass指向了PHP-FPM的监听地址。这里要特别强调unix:/run/php-fpm/www.sock这个路径必须和PHP-FPM配置里的listen一致否则会出现502错误fastcgi_param SCRIPT_FILENAME这一行定义了要执行的PHP脚本的绝对路径是Nginx和PHP-FPM协同工作的核心参数写完配置文件后检验一下语法nginx -t如果输出syntax is ok和test is successful说明配置没有问题重新加载Nginxsystemctl reload nginx # yum安装方式 # 或 /usr/local/nginx/sbin/nginx -s reload # 编译安装方式5.3 验证PHP与数据库连通性在站点目录下新建一个info.php文件用来确认PHP正常解析?php phpinfo(); ?浏览器访问http://你的服务器IP/info.php如果能看到PHP信息页面说明Nginx和PHP-FPM已经打通了。不过这里要提醒phpinfo()页面会暴露PHP版本、扩展路径、系统信息等关键敏感信息生产环境用完之后必须立刻删除否则会给攻击者提供很有价值的情报。测试完就删rm -f /data/wwwroot/blog.test.com/info.php接着测试PHP与数据库的连通性?php $conn new mysqli(localhost, root, 你的密码); if ($conn-connect_error) { die(连接失败: . $conn-connect_error); } echo 数据库连接成功; $conn-close(); ?能输出“数据库连接成功”说明PHP和数据库之间的链路也是通的。到这里一个完整的LNMP环境就算搭建完毕了。5.4 部署一个真实站点以WordPress为例环境搭好了最好再拿一个真实应用验证一遍。WordPress是使用LNMP最常见的场景之一用它来验收这套环境再合适不过。先创建WordPress需要的数据库mysql -uroot -pCREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; GRANT ALL PRIVILEGES ON wordpress.* TO wpuserlocalhost IDENTIFIED BY wp_pass_123; FLUSH PRIVILEGES; EXIT;这里的权限设置值得多说一句给应用建独立账号并只授予它对应数据库的权限是数据库安全的最佳实践。不要偷懒让WordPress直接使用root账号连接数据库一旦应用被注入攻击者拿到的就是数据库的最高权限。下载WordPress源码并解压到站点目录cd /data/wwwroot/blog.test.com wget https://wordpress.org/latest.tar.gz tar -zxvf latest.tar.gz --strip-components1 chown -R www:www /data/wwwroot/blog.test.com浏览器访问站点按照安装向导填入数据库信息就能进入WordPress的安装界面了。如果你在安装过程中遇到数据库连接失败优先检查三处数据库是否创建成功、账号权限是否赋予、wp-config.php中的数据库名和密码是否一致。6. LNMP搭建高频问题排查与避坑实录6.1 经典502 Bad Gateway错误排查LNMP搭建过程中502是最常见的错误几乎每个入坑的朋友都会遇到。它本质上是Nginx无法从PHP-FPM获得有效响应。第一次遇到502时别慌按下面的顺序排查第一步确认PHP-FPM进程是否存活ps -ef | grep php-fpm如果看不到master process直接启动PHP-FPM。如果看到大量子进程处于僵死状态则考虑是PHP-FPM的进程池配置问题。第二步确认Nginx配置里的fastcgi_pass和PHP-FPM实际监听的地址一致。这是最容易踩坑的地方# 查看PHP-FPM监听什么地址 grep listen /etc/php-fpm.d/www.conf # 检查Nginx配置里fastcgi_pass指向哪 grep fastcgi_pass /etc/nginx/conf.d/*.conf两种常见组合是PHP-FPM监听127.0.0.1:9000Nginx配置fastcgi_pass 127.0.0.1:9000PHP-FPM监听/run/php-fpm/www.sockNginx配置fastcgi_pass unix:/run/php-fpm/www.sock两者只要对不上502没跑。第三步看PHP-FPM日志这是最直接的信息源tail -f /var/log/php-fpm.log日志里如果有类似WARNING: [pool www] server reached pm.max_children的提示说明进程池已满需要提高pm.max_children的值或优化业务代码。6.2 403 Forbidden错误处理思路403虽然不如502频繁但也很让人头疼。最常见的403是因为站点目录权限不对。Nginx的worker进程以nginx用户运行需要对该目录有读权限而nginx用户对目录的访问权限取决于other位的权限设置。排查方式# 查看目录权限 ls -ld /data/wwwroot/blog.test.com # 确认Nginx用户 ps -ef | grep nginx如果目录属主是root且权限是700那nginx用户肯定进不去。改成合适的权限chown -R nginx:nginx /data/wwwroot/blog.test.com # 或 chmod -R 755 /data/wwwroot/blog.test.com另外一种403是因为index指令里没有配置对应的索引文件名比如站点目录下只有index.php但配置里写的是index index.html index.htm那访问目录时就会因为找不到文件而返回403。解决方法是把index.php放到最前面。如果确认权限和索引都没问题记得检查SELinux是否拦截了访问# 查看SELinux日志 grep nginx /var/log/audit/audit.log | tail -n 20如果有denied关键字的记录基本就是SELinux在作祟。要么按上文调整布尔值要么在测试环境直接关闭SELinux。6.3 数据库连接失败检查清单数据库连接失败的报错五花八门有Cant connect to MySQL server有Access denied for user我总结了一个排查清单基本能覆盖九成情况数据库服务是否在运行systemctl status mariadb端口是否监听ss -tlnp | grep 3306账号密码是否正确mysql -u用户名 -p密码账号是否有远程访问权限默认情况下rootlocalhost只能本机登录如果PHP脚本在另一台机器上连接数据库需要创建带%host的账号防火墙是否放行3306端口如果需要远程连接的话针对Access denied这是权限问题按顺序执行以下SQL排查SELECT user, host, authentication_string FROM mysql.user;确认你要用到的账号是否存在、host是否匹配。比如你MySQL的账号是wpuserlocalhost但PHP连接时用的host是127.0.0.1有时也会因匹配问题导致认证失败。此时把host改成%或127.0.0.1即可。6.4 从实际踩坑中总结的几条提醒这轮LNMP搭建走下来有几个细节是我反复踩坑后总结出来的单独列出来希望能帮你少走弯路第一个提醒是关于PHP-FPM运行用户和目录权限的一致性。Nginx、PHP-FPM、站点目录属主这三者的用户权限尽量保持一致。如果Nginx运行在nginx用户下PHP-FPM运行在www用户下站点目录属主是nginx那么PHP-FPM写入文件时就会遇到权限不足的问题。最理想的配置是把Nginx和PHP-FPM的用户都统一成同一个比如都改成www用户。第二个提醒是改配置后一定记得重载服务。很多人改完nginx.conf后忘了nginx -s reload改完php.ini后忘了重启PHP-FPM排查了半天结果发现配置压根没生效。第三个提醒是生产环境记得关掉display_errorsdisplay_errors Off log_errors On让PHP错误信息写入日志而不是直接输出到浏览器既避免暴露敏感路径信息也方便统一收集和分析错误。6.5 安全加固与日常维护建议一个LNMP环境跑起来只是一切开始后续的安全加固和日常维护同样重要。这里分享几个实用建议第一修改SSH默认端口并禁止root直接登录是防暴力破解的第一道防线。编辑/etc/ssh/sshd_config修改Port字段并设置PermitRootLogin no然后重启sshd服务。改完记得先开新终端测试能否登录再退出旧连接不然一旦断连就彻底进不去了。第二给MariaDB做一个每日自动备份。用crontab实现最简单的逻辑备份crontab -e # 每天凌晨3点备份数据库保留最近7天 0 3 * * * mysqldump -uroot -p你的密码 --all-databases | gzip /backup/mysql_$(date %Y%m%d).sql.gz备份文件建议存到独立的数据盘或存储桶别和系统盘放在同一个位置。第三关注LNMP各组件的安全更新。yum安装的可以直接用yum update编译安装的则需要定期检查官网版本并手工升级。安全无小事尤其是对外提供服务的Web服务器及时补漏洞是做这行的底线。这套LNMP环境在整个搭建过程里我自己最深的体会是不管yum还是编译安装本质都是把Nginx、PHP、数据库这三块独立积木拼接起来。理解了它们之间怎么通信、日志怎么看、权限怎么配换到Ubuntu、Debian也好换到宝塔面板也好底层逻辑都是相通的。如果你在实操中遇到文章中没提到的奇怪问题建议先抓Nginx错误日志error.log和PHP-FPM日志九成以上的问题都能从日志里找到线索。
返回列表