温馨提示×

如何排查Linux php-fpm的故障

小樊
51
2025-11-16 15:20:18
栏目: 编程语言

Linux 上排查 PHP-FPM 故障的实用流程


一 快速判定与定位

  • 查看服务状态与最近日志
    • 执行:sudo systemctl status php<版本>-fpm,关注是否出现 active (running)failed,以及 journalctl -xeu php<版本>-fpm 的最新报错。
  • 确认进程与监听
    • 进程:pgrep php-fpm
    • 端口:ss -lntp | grep phpnetstat -plnt | grep php
    • Unix 套接字:ls -l /var/run/php/php<版本>-fpm.sock
  • 校验配置语法
    • 执行:sudo php-fpm<版本> -t(或 php-fpm -t,取决于 PATH),确保配置无语法错误。
  • 查看错误日志
    • 常见路径:/var/log/php<版本>-fpm.log/var/log/php-fpm.log/var/log/php/<版本>/fpm.log 或自定义路径;使用 tail -f 实时观察。
  • 若已启用状态页,做连通性自检
    • www.conf 中确认 pm.status_path(如 /status),访问 http://localhost/status 检查 pool、processes、idle/active 等状态是否正常。

二 常见故障与修复对照表

症状 快速检查 修复建议
服务无法启动 systemctl statusjournalctlphp-fpm -t 修正配置语法;若报 Permission denied,确保日志/运行目录对 运行用户(如 www-data、nginx、apache) 可写;必要时 chown/chmod 并重启
端口被占用(如 9000 `ss -lntp grep 9000`
Unix 套接字不存在/权限错误 ls -l /var/run/php/php*.sock 确认 listenNginx/前置代理一致;检查 socket 目录权限与属主;必要时 systemctl restart php-fpm 重建
权限/SELinux 导致初始化失败 日志出现 failed to open error_log: Permission denied 修正日志/目录属主与权限;若启用 SELinux,临时 setenforce 0 验证,定位后用 chcon 设置正确类型并恢复 Enforcing
502/504 网关错误 访问返回 502/504,FPM 进程存在或队列满 检查 FPM 与 Nginx 的 listen/pass 路径或端口一致;查看 慢日志进程占用;必要时调大 pm.max_children、listen.backlog 并优化慢请求

三 性能与慢请求定位

  • 开启慢日志
    • www.conf 中设置:
      • slowlog = /var/log/php-fpm/slow.log
      • request_slowlog_timeout = 1s(按需调整为 1000ms 等)
    • 重启:sudo systemctl restart php<版本>-fpm
  • 实时查看与分析
    • 实时跟踪:tail -f /var/log/php-fpm/slow.log
    • 辅助分析:结合 Xdebug/Blackfire/PHP Profiler 做更深入的性能剖析与热点定位。

四 配置与运维要点

  • 进程与队列
    • 结合负载与内存调优 pm.max_children、pm.start_servers、pm.min_spare_servers、pm.max_spare_servers;高并发场景适当增大 listen.backlog(如 1024),避免队列溢出导致 504
  • 监听方式一致性
    • FPM 的 listen(如 127.0.0.1:9000/run/php/php<版本>-fpm.sock)必须与 Nginx fastcgi_pass 完全一致(含地址、端口或套接字路径)。
  • 运行用户与目录权限
    • 确认 user/group 与网站目录、日志目录、运行时目录(如 /run/php-fpm)权限匹配,避免因权限不足导致 无法写日志/无法创建 socket
  • 状态页与监控
    • 启用并保护 pm.status_path,配合 Nginx 访问控制 或内网白名单,定期巡检 processes、queue、slow requests 等指标。

五 一键排查脚本示例

#!/usr/bin/env bash
set -Eeuo pipefail

PHP_VER=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')
FPM_SERVICE="php${PHP_VER}-fpm"
FPM_POOL="/etc/php/${PHP_VER}/fpm/pool.d/www.conf"
SOCK_PATH=$(grep -E '^listen\s*=' "$FPM_POOL" | awk '{print $3}' | head -n1)
LOG_ERR=$(grep -E '^error_log\s*=' "$FPM_POOL" | awk '{print $3}' | head -n1)
LOG_SLOW=$(grep -E '^slowlog\s*=' "$FPM_POOL" | awk '{print $3}' | head -n1)

echo "=== $FPM_SERVICE 状态 ==="
systemctl is-active --quiet "$FPM_SERVICE" && echo "active" || { echo "inactive"; journalctl -xeu "$FPM_SERVICE" | tail -n50; exit 1; }

echo -e "\n=== 进程与监听 ==="
pgrep -a php-fpm || echo "无 php-fpm 进程"
ss -lntp | grep -E "php|9000|$SOCK_PATH" || echo "未检测到监听"

echo -e "\n=== 配置语法 ==="
php-fpm${PHP_VER} -t

echo -e "\n=== 关键文件与权限 ==="
ls -ld "$(dirname "$SOCK_PATH")" 2>/dev/null || echo "Socket 目录不存在: $(dirname "$SOCK_PATH")"
[ -n "$LOG_ERR" ] && ls -l "$LOG_ERR" 2>/dev/null || echo "错误日志未配置或不存在: $LOG_ERR"
[ -n "$LOG_SLOW" ] && ls -l "$LOG_SLOW" 2>/dev/null || echo "慢日志未配置或不存在: $LOG_SLOW"

echo -e "\n=== SELinux 状态 ==="
getenforce 2>/dev/null || echo "SELinux 未安装"

echo -e "\n=== 提示 ==="
echo "若 Nginx 报 502/504,请核对 fastcgi_pass 与 FPM 的 listen 一致,并查看慢日志与进程占用。"

将脚本保存为 check_fpm.sh,执行:chmod +x check_fpm.sh && sudo ./check_fpm.sh

0