Nginx集成篇01—与PHP集成

概述

本章,您将学习到如何将 Nginx 和 PHP 一起搭配使用,构建动态网站。

工作原理

您需要首先在 Nginx 当作做相应的 FastCGI 配置,配置完成后,当客户端或浏览器请求 PHP 资源时,Nginx 会将请求转发给 PHP-FPM 进行处理。在这套组合中,Nginx 负责静态资源处理和请求转发,PHP-FPM 则专注于解析 PHP 代码。

术语说明如下:

  • CGI(Common Gateway Interface,通用网关接口):底层本质是一套开放式通信协议,用于规范 Web 服务器与动态脚本程序之间的数据交互格式;日常语境中也指代基于该协议衍生出的动态响应生成技术。传统 CGI 因性能缺陷问题已基本淘汰,当前行业中主流使用的是它的高性能改进版本,即 FastCGI。
  • PHP-FPM:PHP 专属的 FastCGI 进程管理器,作为 FastCGI 协议的后端实现,负责 PHP 代码的解析执行,最终生成 HTML 响应返回给 Nginx

工作流程图如下:

⏳

正在加载 Flowchart 图表...

环境说明

环境说明如下:

角色 IP 地址 OS 安装方式 版本
Web 服务器(Nginx) 192.168.100.20/24 RL 8.10 源码编译安装 1.31.5
编程语言(PHP) 192.168.100.21/24 RL 10.2 源码编译安装 8.5.11

同 Nginx 一样,PHP 编程语言由于不太需要经常变动,因此建议在机器数量较少的情况下(少于 10 台机器)使用源码编译安装的方式。

友情提示
在 LAMP 架构中,若 Apache httpd、MySQL、PHP 均采用源码编译安装的方式,则在安装 PHP 之前,您必须先安装 Apache httpd,因为 PHP 需要被编译成 Apache httpd 的一个 DSO 模块(动态加载模块、动态模块),嵌入到 Apache httpd 进程中运行,具体来说,PHP 的编译选项 --with-apxs2=[FILE] 依赖 Apache httpd 的 apxs 二进制文件。但在 LNMP 架构中则不太一样,若 Nginx、MySQL、PHP 均采用源码编译安装的方式,则无先后编译安装顺序,因为 Nginx 和 PHP 通过 FastCGI 协议进行通信。

PHP

安装 PHP

PHP 编译安装的过程如下:

Shell > wget -c https://www.php.net/distributions/php-8.5.11.tar.gz

Shell > tar -vxf php-8.5.11.tar.gz -C /usr/local/src/

Shell > cd /usr/local/src/php-8.5.11/

Shell > ./configure \
--prefix=/usr/local/php8.5 \
--with-fpm-user=nobody \
--with-fpm-group=nobody \
--with-config-file-path=/usr/local/php8.5/etc \
--enable-fpm \
--enable-calendar \
--with-zlib \
--with-zip \
--with-bz2 \
--with-curl \
--with-openssl \
--enable-gd \
--enable-bcmath \
--with-webp \
--with-jpeg \
--with-xpm \
--with-xsl  \
--with-freetype \
--with-mhash \
--with-gettext \
--enable-mbstring \
--enable-intl \
--enable-mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-mysqli \
--enable-pcntl \
--enable-shmop \
--enable-soap \
--enable-sockets \
--enable-sysvmsg \
--enable-sysvsem \
--enable-sysvshm \
--disable-ipv6 \
--disable-cgi \
&& make && make install

可能会缺少编译环境对应的依赖软件包,执行以下命令即可("\" 表示命令交互未结束):

Shell > dnf5 -y install gcc gcc-c++ libxml2 libxml2-devel \
openssl openssl-devel curl curl-devel sqlite sqlite-devel \
libicu libicu-devel oniguruma oniguruma-devel zip libzip libzip-devel \
libpng libpng-devel libwebp libwebp-devel libxslt libxslt-devel \
libjpeg-turbo libjpeg-turbo-devel libXpm libXpm-devel \
freetype freetype-devel bzip2 bzip2-devel cmake 

其中部分依赖软件包存放在 devel 存储库中,开启这个 devel 存储库即可:

Shell > sed -i '1,12s/'enabled=0'/'enabled=1'/g' /etc/yum.repos.d/rocky-devel.repo

编译安装结束后的目录:

Shell > ls -l /usr/local/php8.5/
total 28
drwxr-xr-x 2 root root 4096 Oct 20 23:32 bin
drwxr-xr-x 3 root root 4096 Oct 20 23:31 etc
drwxr-xr-x 3 root root 4096 Oct 20 23:31 include
drwxr-xr-x 3 root root 4096 Oct 20 23:31 lib
drwxr-xr-x 4 root root 4096 Oct 20 23:31 php
drwxr-xr-x 2 root root 4096 Oct 20 23:31 sbin
drwxr-xr-x 4 root root 4096 Oct 20 23:31 var

复制源码中的文件到安装后的配置目录(PHP 的配置文件以 .ini 结尾):

Shell > cp -p /usr/local/src/php-8.5.11/php.ini-production /usr/local/php8.5/etc/php.ini

类似 RL 9.x 和 RL 10.x 中 NetworkManager 网卡配置文件的 init 风格,php.ini 配置文件的结构说明如下:

  • 以 ; 开头表示注释行
  • 使用 "[" 和 "]" 包含声明的节标题,在节标题的下方则是具体的键值对,在下一个节标题出现之前的所有键值对都属于对应的节标题
  • 键值对中等号两边可以允许有空格,也允许没有空格

RL 9.x 和 RL 10.x 中 NetworkManager 网卡配置文件的部分内容:

Shell > cat /etc/NetworkManager/system-connections/ens160.nmconnection
[connection]
id=ens160
uuid=5903ac99-e03f-46a8-8806-0a7a8424497e
type=ethernet
interface-name=ens160
timestamp=1670056998

[ethernet]
mac-address=00:0C:29:47:68:D0

[ipv4]
address1=192.168.100.4/24,192.168.100.1
dns=8.8.8.8;114.114.114.114;
method=manual
...

php.ini 文件的部分内容(去掉了注释行与空白行):

Shell > grep -v -E "^$|^;" /usr/local/php8.5/etc/php.ini
[PHP]
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions =
zend.enable_gc = On
...
[Date]
...

配置 PHP

php.ini 文件暂时先不修改,但是需要修改与 php-fpm 相关的内容。步骤如下:

# 创建系统用户 nginx 和系统用户组 nginx
Shell > groupadd -r nginx
Shell > useradd -r -g nginx nginx
Shell > id nginx
uid=994(nginx) gid=994(nginx) groups=994(nginx)

# 输出重定向
Shell > cat /usr/local/php8.5/etc/php-fpm.d/www.conf.default > /usr/local/php8.5/etc/php-fpm.d/www.conf

# 修改 www.conf 文件
Shell > vim /usr/local/php8.5/etc/php-fpm.d/www.conf
[www]
; 修改
user = nginx
; 修改
group = nginx

; 修改这行
listen = 192.168.100.21:9000

; 添加这行
listen.allowed_clients = 192.168.100.20

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

# 接着使用重定向生成 php-fpm.conf 文件:
Shell > cat /usr/local/php8.5/etc/php-fpm.conf.default > /usr/local/php8.5/etc/php-fpm.conf

# 测试 /usr/local/php8.5/etc/php-fpm.conf 文件
Shell > /usr/local/php8.5/sbin/php-fpm -t
[23-Oct-2026 21:50:28] NOTICE: configuration file /usr/local/php8.5/etc/php-fpm.conf test is successful

创建需要的目录(后面会说明为什么需要这么做):

Shell > mkdir -p /var/html/tests/

变更文件所有者和所属组:

Shell > chown -R nginx:nginx /var/html/tests/

Shell > chown nginx:nginx /usr/local/php8.5/etc/php-fpm.conf /usr/local/php8.5/etc/php-fpm.d/www.conf

启动 php-fpm

启动 php-fpm:

Shell > /usr/local/php8.5/sbin/php-fpm

# 查看套接字和端口信息
Shell > ss -tulnp
Netid        State         Recv-Q        Send-Q                Local Address:Port               Peer Address:Port       Process
udp          UNCONN        0             0                         127.0.0.1:323                     0.0.0.0:*           users:(("chronyd",pid=827,fd=4))
udp          UNCONN        0             0                             [::1]:323                        [::]:*           users:(("chronyd",pid=827,fd=5))
tcp          LISTEN        0             128                         0.0.0.0:22                      0.0.0.0:*           users:(("sshd",pid=904,fd=7))
tcp          LISTEN        0             4096                 192.168.100.21:9000                    0.0.0.0:*           users:(("php-fpm",pid=2763,fd=6),("php-fpm",pid=2762,fd=6),("php-fpm",pid=2761,fd=8))
tcp          LISTEN        0             128                            [::]:22                         [::]:*           users:(("sshd",pid=904,fd=8))

Nginx

配置 Nginx

在 Nginx 主配置文件中,核心是需要通过 fastcgi_pass 指令指向 php-fpm 所在的 IP 地址和端口。

# 先创建需要的目录
Shell > mkdir -p /var/html/tests/

Nginx 的示例配置如下:

user  nginx;
worker_processes  auto;

error_log  logs/error.log  error;

pid        logs/nginx.pid;

events {
    use epoll;
    worker_connections  1024;
    multi_accept on;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    sendfile       on;
    tcp_nopush     on;

    keepalive_timeout  30;
    server_tokens off;

    gzip on;
    gzip_vary on;
    gzip_buffers 32 4K;
    gzip_comp_level 5;
    gzip_types text/plain text/css text/xml application/json application/javascript application/xml application/xhtml+xml image/svg+xml application/x-font-ttf application/x-font-opentype application/vnd.ms-fontobject font/woff;
    gzip_min_length 256;

    upstream php8 {
        server 192.168.100.21:9000;
        keepalive 15;
    }

    server {
        listen  192.168.100.20:80;
        server_name my-tests.com www.my-tests.com;
        access_log  logs/my-tests.log  main;
        charset utf-8;

        root   /var/html/tests/;
        index  index.php index.html index.htm;

        # 禁止访问隐藏文件,隐藏文件即点文件
        location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
        }

        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }

        # 使用不区分大小写的正则表达式匹配
        location ~* \.php$ {
                try_files $uri =404;
                fastcgi_keep_conn on;

                # 关键配置
                fastcgi_pass php8;

                # 关键配置
                fastcgi_index index.php;

                # 关键配置:必须包含标准 FastCGI 参数,fastcgi_params 文件默认存在于 /usr/local/nginx/conf/ 目录中
                include fastcgi_params;

                # 关键配置
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

                # 可选优化配置
                fastcgi_connect_timeout 5s;
                fastcgi_send_timeout 30s;
                fastcgi_read_timeout 30s;
        }
    }
}

说明如下:

  • 定义一个名为 php8 且启用长连接的上游服务器。keepalive 指令的指令参数默认只对 proxy_pass 指令生效。
  • Nginx 的网页根目录为 /var/html/tests/
  • log_not_found 指令 - 当文件未找到时,是否将相关记录写入到错误文件中(error_log 指令指定的错误文件)
  • try_files - 按照顺序检查文件或目录是否存在,一旦找到第一个对应文件,Nginx 会停止后续检查。PHP 常见配置为 try_files $uri $uri/ /index.php?$query_string;,即 "静态资源优先,动态请求兜底"
  • try_files $uri =404; - 文件不存在时直接返回 404 状态码,不用转发给 PHP 进行处理
  • fastcgi_keep_conn on; - 对对应的 FastCGI 服务器启用 TCP 长连接功能,主要是搭配 upstream 上下文中的 keepalive 16;
  • fastcgi_index index.php; - 设置一个文件名,该文件名将被追加到以斜杠结尾的 URI 之后,并作为 $fastcgi_script_name 变量的值
  • fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - 该指令用来设置一个应传递给 FastCGI 服务器的参数,此处 SCRIPT_FILENAME 表示参数名,$document_root$fastcgi_script_name 表示参数的值,用 $ 表示相关的 Nginx 内置变量

    • $document_root - Nginx 的内置变量,该值为 root 指令或 alias 指令的指令参数
    • $fastcgi_script_name - Nginx 的内置变量,表示当前请求中 URI 中被匹配为 PHP(或其他 FastCGI)脚本的那部分路径,用于告诉 PHP 应该执行哪个文件

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 这条指令的含义:

  1. 取 Nginx 的网页根目录($document_root,如 /var/html/tests)
  2. 拼接上请求的脚本路径($fastcgi_script_name,如 index.php)
  3. 将结果 /var/html/tests/index.php 赋值给 FastCGI 参数 SCRIPT_FILENAME
  4. PHP-FPM 通过 FastCGI 协议接收来自 Nginx 的文件路径字符串,在本地文件系统中查找 /var/html/tests/index.php 文件并执行该文件

启动 Nginx

Shell > usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

Shell > ss -tulnp
Netid         State          Recv-Q         Send-Q                                       Local Address:Port                   Peer Address:Port         Process
udp           UNCONN         0              0                                                127.0.0.1:323                         0.0.0.0:*             users:(("chronyd",pid=779,fd=5))
udp           UNCONN         0              0                                                    [::1]:323                            [::]:*             users:(("chronyd",pid=779,fd=6))
udp           UNCONN         0              0                        [fe80::20c:29ff:feb3:41fd]%ens160:546                            [::]:*             users:(("NetworkManager",pid=774,fd=24))
tcp           LISTEN         0              128                                                0.0.0.0:22                          0.0.0.0:*             users:(("sshd",pid=795,fd=3))
tcp           LISTEN         0              511                                         192.168.100.20:80                          0.0.0.0:*             users:(("nginx",pid=5947,fd=6),("nginx",pid=5946,fd=6),("nginx",pid=5945,fd=6))
tcp           LISTEN         0              128                                                   [::]:22                             [::]:*             users:(("sshd",pid=795,fd=4))

关联

在 Nginx 服务器上:

Shell > vim /var/html/tests/index.php
<?php
phpinfo();
?>

在 PHP 服务器上:

Shell > vim /var/html/tests/index.php
<?php
phpinfo();
?>

在浏览器上访问 http://192.168.100.20 则会出现这样的一个页面:

PHP-info

注意事项

  1. 两台机器的文件必须保持一致且同步

    • Nginx(192.168.100.20/24) - 负责存储静态文件和 PHP 源代码
    • PHP(192.168.100.21/24)- 负责执行代码。通过 FastCGI 协议接收来自 Nginx 的文件路径字符串并在本地文件系统中寻找对应文件

    由于 Nginx 和 PHP 在不同的机器上且分工不同,导致了两台机器的文件必须保持一致且同步,您可以通过相关工具(如 rsync)完成机器之间的文件同步。
    若 Nginx 服务器上有 /var/html/tests/index.php 文件,则 PHP 服务器上也必须有 /var/html/tests/index.php 文件。

  2. 权限一致性

    若 Nginx 的进程使用 nginx 用户运行,除了 PHP 的 php-fpm 应该以 nginx 用户运行外,关联文件的文件所有者和所属组也应该设置为 nginx 用户和用户组

Avatar photo

关于 陸風睿

GNU/Linux 从业者、开源爱好者、技术钻研者,撰写文档既是兴趣也是工作内容之一。Q - "281957576";WeChat - "jiulongxiaotianci",Github - https://github.com/jimcat8
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇