LNMP环境编译安装:手动编译Nginx 1.26+PHP 8.3+MySQL 8.0的配置参数
LNMP 编译安装失败,多数不是命令敲错,而是配置参数之间没对齐。本文用一个站群部署案例,把 Nginx 1.26、PHP 8.3、MySQL 8.0 的编译顺序、关键参数和联调验证走一遍。
场景:一台 4 核 8G 的站群机,要求特定版本
客户手上是一台 4 核 8G 的云主机,准备用 188CMS 跑一批中文站,程序要求较新的 PHP,而系统源里的 PHP 还停在 7.x 量级,MySQL 也只有 5.7。于是需求变成:Nginx 用 1.26 系列,PHP 用 8.3 系列,MySQL 用 8.0 系列,全部走源码编译。
这类需求通常来自三种情况:需要系统源里没有的模块,比如 stream、http_v3;需要在编译阶段就做模块和性能取舍;一台机器上要跑十几个站点,对内存分配特别敏感。三种情况有一个共同点——参数必须自己定,装完再改的成本很高。
先理依赖和版本约束,别急着 configure
编译前先把依赖装齐,否则 configure 会一个个报错让你来回找。以 RHEL 系为例:
yum install -y gcc gcc-c++ make cmake \
pcre2-devel zlib-devel openssl-devel \
libxml2-devel sqlite-devel oniguruma-devel \
libcurl-devel libjpeg-turbo-devel libpng-devel \
freetype-devel libzip-devel bzip2-devel
Debian/Ubuntu 系换成 apt install build-essential libpcre2-dev zlib1g-dev libssl-dev 加对应的图形库包。三个组件的依赖有重叠也有冲突:PHP 8.3 需要 oniguruma 和 libzip,MySQL 8.0 需要 Boost 和 ncurses。装完用 gcc -v 确认版本,过新的 GCC 编译 MySQL 偶尔会报错,可以加 -DCMAKE_CXX_FLAGS="-Wno-error" 绕过。
环节一:Nginx 的模块取舍
./configure --prefix=/usr/local/nginx \
--user=www --group=www \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-stream \
--with-pcre --with-zlib --with-openssl
make -j4 && make install
参数取舍的逻辑很直接:--with-http_realip_module 在套 CDN 时必须有,否则日志里全是回源 IP,做分析和封禁都无从下手;--with-http_stub_status_module 用来接监控;--with-stream 是四层转发,不跑数据库代理就不用加。不需要的模块不要顺手带上,模块越多二进制越大,出安全更新后重编译越费事。
HTTP/3 要额外挂 --with-http_v3_module,并且依赖较新的 OpenSSL 或 quictls,具体支持情况以官方发布说明为准。Nginx 1.26 属于 1.25 之后的主线稳定分支,HTTP/2 已稳定,HTTP/3 仍是可选项,按需开。
环节二:PHP 8.3 的 FPM 与扩展绑定
./configure --prefix=/usr/local/php \
--with-fpm-user=www --with-fpm-group=www \
--enable-fpm --enable-opcache --enable-mysqlnd \
--with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd \
--with-openssl --with-zlib --with-curl --with-zip \
--enable-gd --with-jpeg --with-freetype \
--with-config-file-path=/usr/local/php/etc
make -j4 && make install
两个位置最容易踩:--with-fpm-user 必须和 Nginx 的 --user 保持一致,否则 PHP 生成的文件 Nginx 读不到,表现为 403;--with-config-file-path 不写死,php.ini 会找不到,改配置全靠猜。装完把源码目录里的 php.ini-production 拷成 php.ini,打开 opcache.enable=1,按需设置 opcache.jit(JIT 默认关闭),再调 date.timezone、memory_limit、upload_max_filesize。参数名有没有变,用 ./configure --help | grep 关键词 查最快。
环节三:MySQL 8.0 的内存参数比编译参数更值钱
MySQL 8.0 从源码编译,耗时通常在几十分钟到数小时这个量级,取决于核数与磁盘。如果只是要 8.0 版本本身,官方 tar 包解压更快;坚持编译一般是需要定制字符集或安装路径。
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_DATADIR=/data/mysql \
-DSYSCONFDIR=/etc \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_0900_ai_ci \
-DWITH_BOOST=../boost
初始化:/usr/local/mysql/bin/mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql。
真正决定性能的是 my.cnf:innodb_buffer_pool_size 在 8G 内存的机器上给 2G 到 3G 比较稳,剩下的留给 PHP-FPM 子进程和系统本身。站群场景连接数多、单连接压力小,可以把 max_connections 调高,但 innodb_flush_log_at_trx_commit 不建议为了性能改成 0,丢数据的代价比那点写入提升大得多。
流程节点:三个组件怎么互认
先各自自检:/usr/local/nginx/sbin/nginx -t、/usr/local/php/sbin/php-fpm -t、mysql -uroot -e "select version()"。再让 Nginx 找到 PHP:
location ~ \.php$ {
fastcgi_pass unix:/dev/shm/php-fpm.sock;
include fastcgi.conf;
}
socket 放 /dev/shm 比走 127.0.0.1:9000 略快,前提是 php-fpm.conf 里 listen.owner、listen.group 和 Nginx 的 worker 用户一致。最后丢一个 phpinfo 文件,用 curl -I http://127.0.0.1/phpinfo.php 访问,返回 200 且页面里能看到 mysqli、opcache 已加载,才算配通。用 php -m 对比 configure 时开的扩展项,缺哪个就是参数写错或依赖没装。
结论:什么样的情况值得手动编译
如果目标只是让站点尽快跑起来,系统源加第三方仓库能省掉大半天。手动编译的价值集中在三点:需要源里没有的模块;需要在参数层面做性能取舍;需要在同一台机器上精确锁定组件版本。代价同样明确——升级要重新编译,PHP 扩展要用 phpize 单独再编一遍,团队里没人熟悉编译环境时,维护成本会高到影响正常迭代。
回到开头那台机器,四核八G、十几个站的量级,上面这套组合是合适的;单站小站则建议直接用包管理版本,把时间花在内容和收录上,而不是编译参数上。