如何重启 PHP-FPM:为 Linux 管理员详解每种方法
PHP-FPM(PHP FastCGI进程管理器)是一个高性能进程管理器,它将PHP执行作为独立服务处理,与Web服务器解耦。重启PHP-FPM可应用来自`php.ini`或`php-fpm.conf`的配置更改,回收长期运行的工作进程池中的内存泄漏,并从无响应的子进程中恢复——所有这些都无需触及Nginx、Apache或您技术栈中的任何其他组件。
本指南涵盖了现代和旧版Linux发行版上所有实用的重启方法,包括基于信号的控制、多版本环境以及零停机生产部署的优雅重载策略。
为什么需要重启PHP-FPM
了解重启的确切触发原因可以防止不必要的停机,并帮助您选择最少干扰的方法:
- 配置更改:对`php.ini`、`php-fpm.conf`或`/etc/php/<version>/fpm/pool.d/`下任何池配置文件的修改都需要重启或重载才能生效。PHP-FPM仅在启动时或收到`USR2`信号时读取这些文件。
- 内存回收:PHP-FPM工作进程会随时间积累内存,尤其是在运行内存密集型应用程序的高流量服务器上。受控重启可回收工作进程并重置其内存占用。
- 无响应的工作进程:如果子进程进入僵尸状态或停止接受连接,重启将清除进程表并生成新的进程池。
- 日志轮转:在`logrotate`重命名或压缩活动日志文件后,PHP-FPM仍持有旧inode的文件描述符。重载会强制其打开新的文件描述符,确保日志连续性。
- OPcache失效:部署新应用程序代码时,重启PHP-FPM会完全刷新OPcache,确保工作进程执行更新后的字节码,而不是过时的缓存版本。
- 扩展或模块更改:在`php.ini`中添加或删除PHP扩展需要完全重启——仅重载是不够的,因为扩展列表在进程初始化时才会被评估。
前提条件
在执行任何重启命令之前,请确认以下内容:
- 您拥有服务器的`root`访问权限或`sudo`权限。
- 您知道系统上PHP-FPM服务的确切名称(因发行版和已安装版本而异)。
- 如果您计划使用基于信号的控制,您已确定PID文件路径(通常在Debian/Ubuntu上为`/run/php/php<version>-fpm.pid`,在RHEL/CentOS上为`/run/php-fpm/php-fpm.pid`)。
要查找活动的PHP-FPM服务名称:
“`bash
systemctl list-units –type=service | grep fpm
“`
要定位PID文件路径:
“`bash
grep -i pid /etc/php/*/fpm/php-fpm.conf
“`
方法1:使用systemctl重启PHP-FPM(推荐)
`systemctl`是所有基于systemd的发行版上的权威服务管理器,包括Ubuntu 16.04+、Debian 8+、CentOS 7+、AlmaLinux、Rocky Linux和Fedora。它是绝大多数生产服务器的正确工具。
标准重启
“`bash
sudo systemctl restart php8.2-fpm
“`
将`php8.2-fpm`替换为系统上安装的版本(例如`php7.4-fpm`、`php8.1-fpm`、`php-fpm`)。在基于RHEL的系统上,服务通常命名为`php-fpm`,不带版本前缀。
不完全重启的重载
重载会在内部发送`USR2`信号,指示主进程重新读取其配置并优雅地替换工作进程。现有的进行中请求在工作进程被回收之前会先完成:
“`bash
sudo systemctl reload php8.2-fpm
“`
关键区别:`reload`是非中断性的,在生产环境中更适合用于配置更改。`restart`会立即终止所有工作进程,在高并发情况下可能会丢弃活动连接。
分别停止和启动
“`bash
sudo systemctl stop php8.2-fpm
sudo systemctl start php8.2-fpm
“`
当您需要在重新启动之前确认服务已完全停止时,请使用此两步方法——例如,在更改`listen`套接字路径或大幅修改`pm.max_children`之后。
验证服务状态
“`bash
sudo systemctl status php8.2-fpm
“`
正常输出显示`Active: active (running)`并列出主进程PID。如果服务启动失败,`systemctl status`会显示最后的日志条目,这比手动查找日志文件更快。
要在重启期间实时流式传输日志:
“`bash
sudo journalctl -u php8.2-fpm -f
“`
方法2:使用旧版service命令重启PHP-FPM
`service`命令是现代系统上`systemctl`的兼容性包装器,在旧版发行版(Ubuntu 14.04、CentOS 6、Debian 7)上直接调用SysVinit脚本。在管理尚未迁移到systemd的服务器时,它仍然适用。
“`bash
sudo service php-fpm restart
“`
要独立停止和启动:
“`bash
sudo service php-fpm stop
sudo service php-fpm start
“`
在仍使用SysVinit的发行版上,底层脚本位于`/etc/init.d/php-fpm`。如果`service`包装器不可用,您可以直接调用它:
“`bash
sudo /etc/init.d/php-fpm restart
“`
方法3:同时管理多个PHP版本
运行cPanel、Plesk等控制面板或自定义多租户设置的服务器通常并行安装了多个PHP版本。每个版本作为独立的PHP-FPM服务运行,拥有自己的配置树、套接字和PID文件。
重启特定版本
“`bash
Debian/Ubuntu (packages from ondrej/php PPA or distribution repos)
sudo systemctl restart php7.4-fpm
sudo systemctl restart php8.1-fpm
sudo systemctl restart php8.2-fpm
RHEL/CentOS with Remi repository
sudo systemctl restart php74-php-fpm
sudo systemctl restart php81-php-fpm
“`
一次重启所有PHP-FPM版本
当系统范围的更改影响所有版本时(例如共享库更新),使用单个循环重启所有实例:
“`bash
for ver in 7.4 8.1 8.2; do
sudo systemctl restart php${ver}-fpm && echo "php${ver}-fpm restarted"
done
“`
确定哪个版本为特定站点提供服务
每个Nginx虚拟主机或Apache VirtualHost都映射到特定的PHP-FPM套接字。在重启之前,检查站点配置以确定哪个版本处于活动状态:
“`bash
Nginx
grep fastcgi_pass /etc/nginx/sites-enabled/yourdomain.conf
Apache with mod_proxy_fcgi
grep SetHandler /etc/apache2/sites-enabled/yourdomain.conf
“`
如果您通过控制面板管理服务器,带cPanel的VPS提供了一个图形界面,可以按域名切换PHP版本,无需手动重启服务。
方法4:直接向主进程发送POSIX信号
PHP-FPM的主进程响应一组定义好的POSIX信号。此方法完全绕过init系统,为您提供精确的低级控制——在容器化环境、自定义init系统或`systemctl`不可用时至关重要。
信号参考表
| 信号 | 效果 | 使用场景 |
|---|---|---|
| — | — | — |
| `SIGTERM`(15) | 优雅关闭 | 有序停止,等待工作进程完成 |
| `SIGINT`(2) | 立即关闭 | 当优雅关闭挂起时强制停止 |
| `SIGQUIT`(3) | 优雅停止 | 等同于PHP-FPM的SIGTERM |
| `SIGUSR1`(10) | 重新打开日志文件 | 日志轮转后刷新日志文件描述符 |
| `SIGUSR2`(12) | 优雅重载 | 重载配置,不中断连接地回收工作进程 |
| `SIGKILL`(9) | 强制终止 | 最后手段——无清理,无优雅处理 |
重载配置(零停机)
“`bash
sudo kill -USR2 $(cat /run/php/php8.2-fpm.pid)
“`
这在功能上等同于`systemctl reload`,是在生产服务器上应用`php-fpm.conf`或池配置更改的最安全方式。
日志轮转后重新打开日志文件
“`bash
sudo kill -USR1 $(cat /run/php/php8.2-fpm.pid)
“`
在`logrotate`执行后立即运行此命令,以防止PHP-FPM继续向重命名的日志文件写入。
优雅关闭
“`bash
sudo kill -QUIT $(cat /run/php/php8.2-fpm.pid)
“`
主进程停止接受新连接,并等待所有活动工作进程完成其当前请求后再退出。之后执行`sudo systemctl start php8.2-fpm`以重新启动服务。
重要提示:使用这些命令之前,请务必验证PID文件路径。路径不正确会导致向无关进程发送信号。请通过以下命令确认:
“`bash
cat /run/php/php8.2-fpm.pid
ps aux | grep php-fpm
“`
方法5:使用pkill或killall强制终止PHP-FPM进程
这是PHP-FPM完全无响应且`systemctl`和基于信号的控制均无效时的最后手段。它会无条件终止所有PHP-FPM进程,这将中断任何进行中的请求。
“`bash
sudo pkill -9 php-fpm
“`
或使用`killall`:
“`bash
sudo killall -9 php-fpm
“`
强制终止后,除非服务由进程监督器管理,否则不会自动重启。请显式启动它:
“`bash
sudo systemctl start php8.2-fpm
“`
何时使用:僵尸进程积累、失控子进程占用100% CPU,或主进程存活但不再管理其进程池的情况。在使用`pkill -9`之前,先尝试对主进程PID使用`kill -QUIT`——这种方式干扰性小得多。
方法6:重启Web服务器以间接影响PHP-FPM
重启Nginx或Apache不会重启PHP-FPM。由于PHP-FPM作为完全独立的服务通过Unix套接字或TCP端口进行通信,Web服务器重启只影响HTTP层。这是一个常见的误解。
“`bash
Nginx
sudo systemctl restart nginx
Apache
sudo systemctl restart apache2
“`
Web服务器重启与PHP-FPM相关的唯一场景是,当您修改了Nginx中的`fastcgi_pass`指令或Apache中的`ProxyPassMatch`规则以指向不同的PHP-FPM套接字时。在这种情况下,Nginx必须重载其配置以连接到新的套接字路径——但PHP-FPM本身仍然需要单独重启。
对于全栈维护,请按正确顺序重启两个服务:先重启PHP-FPM,再重启Web服务器。
对比:PHP-FPM重启方法一览
| 方法 | 命令示例 | 中断级别 | 使用场景 |
|---|---|---|---|
| — | — | — | — |
| `systemctl restart` | `systemctl restart php8.2-fpm` | 中等——丢弃活动连接 | 标准配置更改,开发/预发布环境 |
| `systemctl reload` | `systemctl reload php8.2-fpm` | 无——优雅回收工作进程 | 生产环境配置更改 |
| `kill -USR2` | `kill -USR2 $(cat /run/php/php-fpm.pid)` | 无——优雅重载 | 生产环境、容器化环境 |
| `kill -QUIT` | `kill -QUIT $(cat /run/php/php-fpm.pid)` | 低——等待请求完成 | 维护前的受控关闭 |
| `kill -USR1` | `kill -USR1 $(cat /run/php/php-fpm.pid)` | 无——仅刷新日志文件描述符 | 日志轮转后 |
| `service restart` | `service php-fpm restart` | 中等 | 旧版SysVinit系统 |
| `pkill -9` | `pkill -9 php-fpm` | 高——立即终止 | 无响应进程,最后手段 |
| Web服务器重启 | `systemctl restart nginx` | 仅Web层 | 更新Web服务器配置中的fastcgi套接字路径 |
PHP-FPM池配置:哪些需要重启,哪些只需重载
并非所有配置更改都具有相同的重要性。了解哪些更改需要完全重启,哪些只需简单重载,可以减少不必要的停机时间:
重载(`USR2` / `systemctl reload`)适用于:
- `pm.max_children`、`pm.start_servers`、`pm.min_spare_servers`、`pm.max_spare_servers`
- `request_terminate_timeout`、`request_slowlog_timeout`
- `slowlog`路径更改
- 池文件中的`php_admin_value`和`php_flag`指令
- `access.log`路径更改
需要完全重启的情况:
- 更改`listen`指令(套接字路径或TCP端口)
- 在`php.ini`中添加或删除PHP扩展
- 更改池中的`user`或`group`指令
- 修改`php-fpm.conf`中的`include`路径
- 更新PHP二进制文件本身(版本升级)
生产环境PHP-FPM重启最佳实践
- 在生产服务器上始终优先使用`reload`而非`restart`。重载会优雅地回收工作进程,在生成替代进程之前完成进行中的请求。硬重启会立即断开所有活动连接。
- 重载前验证配置。PHP-FPM提供内置语法检查,可防止加载损坏的配置:
“`bash
sudo php-fpm8.2 -t
Expected output: NOTICE: configuration file … test is successful
“`
- 前后检查日志。查看`/var/log/php8.2-fpm.log`(或您的`php-fpm.conf`中定义的路径)中的`WARNING`或`ERROR`条目,这些条目表明池启动失败。
- 重启后监控工作进程池指标。使用PHP-FPM状态页面(通过池配置中的`pm.status_path`启用)验证重启后预期数量的工作进程处于活动和空闲状态。
- 与部署流水线自动化集成。在CI/CD工作流中,将`systemctl reload php-fpm`作为部署后钩子触发,而不是完全重启。这确保每次代码推送都实现零停机部署。
- 设置`pm.max_requests`以自动回收工作进程。与其定期安排重启来解决内存泄漏,不如配置`pm.max_requests = 500`(或适当的值),在每个工作进程处理固定数量的请求后自动重启。
VPS和独立服务器环境中的PHP-FPM
您使用的重启方法也受托管环境的影响。在具有完整root访问权限的VPS托管计划上,本指南中描述的所有方法都可以不受限制地使用。您可以直接访问`systemctl`、PID文件和进程表。
在独立服务器上,您控制整个硬件栈,还可以使用`pm = ondemand`或`pm = dynamic`精确调整工作进程生成行为,并使用`systemd`插件文件自定义重启策略(例如`Restart=on-failure`、`RestartSec=5s`)。
如果您通过VPS控制面板解决方案管理多个客户站点,PHP-FPM重启操作通常被抽象到面板的UI中,但了解底层命令对于面板本身无响应时的故障排除场景仍然至关重要。
对于需要高PHP并发的应用程序——例如Laravel、WordPress多站点或WooCommerce商店——将PHP-FPM与独立服务器上经过适当调优的池配置配合使用,可以消除共享环境带来的资源争用。
技术决策矩阵:选择正确的重启方法
使用此矩阵根据您的具体情况选择正确的方法:
| 情况 | 推荐方法 |
|---|---|
| — | — |
| 已应用对`php.ini`或池`.conf`文件的更改 | `systemctl reload php<ver>-fpm` |
| 添加了新的PHP扩展 | `systemctl restart php<ver>-fpm` |
| PHP-FPM无响应,主进程存活 | `kill -QUIT <master_pid>`,然后`systemctl start` |
| PHP-FPM完全冻结,无信号响应 | `pkill -9 php-fpm`,然后`systemctl start` |
| 日志轮转后刷新日志文件 | `kill -USR1 <master_pid>` |
| 部署新应用程序代码(OPcache刷新) | `systemctl reload php<ver>-fpm`或`kill -USR2` |
| 更改了`listen`套接字路径 | `systemctl restart php<ver>-fpm` |
| 多个PHP版本,其中一个需要更新 | 仅`systemctl restart php<specific-ver>-fpm` |
| 无systemd的容器化环境 | 通过入口点脚本使用`kill -USR2 <master_pid>` |
| 应用前进行配置语法检查 | 先`php-fpm<ver> -t`,然后重载/重启 |
常见问题
PHP-FPM的`systemctl restart`和`systemctl reload`有什么区别?
`restart`会立即终止所有主进程和工作进程并重新启动,丢弃任何进行中的请求。`reload`向主进程发送`USR2`信号,主进程使用更新后的配置生成新的工作进程,同时现有工作进程在退出前完成其当前请求。在生产环境中始终使用`reload`。
如何在服务器上找到正确的PHP-FPM服务名称?
运行`systemctl list-units –type=service | grep fpm`。在使用`ondrej/php` PPA安装多个版本的Debian/Ubuntu系统上,您将看到类似`php7.4-fpm.service`和`php8.2-fpm.service`的条目。在使用Remi仓库的RHEL/CentOS上,命名约定为`php74-php-fpm.service`。
重启PHP-FPM是否会影响活动的数据库连接或用户会话?
硬重启(`systemctl restart`)会立即终止所有工作进程,这会关闭这些工作进程持有的任何持久数据库连接。存储在文件或数据库中的用户会话不受影响,因为它们独立于PHP-FPM工作进程持久存在。优雅重载(`systemctl reload`)允许工作进程完成其当前请求,因此持久连接会被干净地关闭。
为什么PHP-FPM在重启后无法启动?
最常见的原因是`php.ini`或池配置文件中存在语法错误、端口或套接字路径冲突(另一个进程已在配置的`listen`地址上监听),或套接字目录权限不足。运行`php-fpm<ver> -t`验证配置语法,并检查`journalctl -u php<ver>-fpm`获取确切的错误消息。
我可以在没有root或sudo权限的情况下重启PHP-FPM吗?
在标准Linux安装上不行。PHP-FPM的主进程以root身份运行(它将工作进程的权限降级为配置的`user`/`group`),管理系统服务需要提升的权限。在共享托管环境中,托管提供商通过其控制面板处理PHP-FPM重启。要完全控制PHP-FPM,具有root访问权限的VPS托管计划是合适的解决方案。
