Основные ошибки PHP-FPM: как понять и устранить проблему

19 Sep 2026, 05:45:26
PHP-FPM (PHP FastCGI Process Manager) — менеджер процессов PHP. Он получает PHP-запросы от веб-сервера, например Nginx, запускает PHP-код и возвращает результат.
Схема работы:
Клиент
   ↓
Nginx
   ↓ FastCGI
PHP-FPM
   ↓
PHP
   ↓
БД / файлы / API
   ↓
PHP-FPM
   ↓
Nginx
   ↓
Клиент


Если PHP-FPM остановлен, перегружен, неправильно настроен или не может выполнить PHP-скрипт, сайт может отдавать 502, 504, 500 или работать медленно.

Где искать ошибки

Посмотреть службы PHP-FPM:
systemctl list-units --type=service | grep fpm
Например, для PHP 8.3:
systemctl status php8.3-fpm
Логи:
Куда FPM пишет ошибки, зависит от директивы error_log в php-fpm.conf. На Debian/Ubuntu это часто отдельный файл /var/log/php8.3-fpm.log, а в journalctl попадают в основном сообщения systemd о запуске и остановке службы. Поэтому смотрите оба источника:
grep -E '^\s*error_log' /etc/php/8.3/fpm/php-fpm.conf
tail -n 100 /var/log/php8.3-fpm.log
journalctl -u php8.3-fpm -n 100
journalctl -u php8.3-fpm -f 

Ошибки самого PHP-кода (Fatal error, warnings) пишутся в PHP , который настраивается отдельно от лога FPM. Чтобы вывод воркеров попадал в лог FPM, используйте
catch_workers_output = yes
в настройках пула.

1. server reached pm.max_children

Пример:
WARNING: [pool www] server reached pm.max_children setting (50), consider raising it

Что означает:
Все доступные PHP-FPM workers заняты:
pm.max_children = 50
50 workers → заняты
Новый запрос → ждёт свободный worker
Из-за этого может увеличиваться время ответа и очередь запросов.
Что проверить:
Количество PHP-FPM процессов:
ps aux | grep '[p]hp-fpm'
Память:
free -h
Потребление памяти PHP-FPM:
ps -o pid,rss,cmd -C php-fpm8.3
Если workers действительно постоянно достигают pm.max_children, необходимо выяснить причину.
Не следует просто увеличивать pm.max_children. Каждый worker потребляет RAM, поэтому слишком большое значение может привести к OOM.

2. seems busy

Пример:
WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, and 16 total children

Что означает: сообщение выводится только при
pm = dynamic
, когда количество свободных workers стало меньше pm.min_spare_servers, и FPM запускает новые процессы. Это не значит, что «все workers заняты»: их может быть занято меньше, чем pm.max_children.
Само сообщение не является ошибкой. Оно говорит о всплеске нагрузки или о слишком малых значениях pm.start_servers / pm.min_spare_servers.
Проблема возникает, если пул постоянно доходит до pm.max_children (см. пункт 1) и запросы начинают ждать.

3. child exited on signal 9 (SIGKILL)

Пример:
WARNING: [pool www] child 1234 exited on signal 9 (SIGKILL)

Что означает: процесс PHP-FPM был принудительно завершён. Самая частая причина — нехватка памяти и работа OOM Killer. Другие возможные причины:
  • лимит памяти контейнера или systemd-юнита (cgroup);
  • ручной kill -9;
  • скрипты мониторинга и watchdog, которые убивают «зависшие» процессы.
Проверить:
journalctl -k | grep -Ei 'oom|out of memory|killed process'
dmesg -T | grep -Ei 'oom|out of memory|killed process'

Если есть строка вида:
Out of memory: Killed process 1234 (php-fpm)
проблема связана с нехваткой RAM, а не с параметрами PHP-FPM. Если процесс убит лимитом контейнера или cgroup, сообщение будет другим, например
Memory cgroup out of memory
.
free -h

4. Primary script unknown

Пример:
FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream

Клиент при этом обычно видит
File not found
. и код 404.
Что означает: PHP-FPM не смог найти или открыть PHP-скрипт, путь к которому передал Nginx.
Возможные причины:
  • неправильный root;
  • неправильный SCRIPT_FILENAME;
  • файла действительно нет;
  • ошибка в конфигурации Nginx;
  • Nginx и PHP-FPM видят файловую систему по-разному (разные Docker-контейнеры, chroot): путь есть у Nginx, но не существует для FPM;
  • у пользователя пула нет права входа (x) в один из каталогов по пути к файлу.
Если файл найден, но не читается, или расширение не разрешено, FPM отвечает Access denied. (код 403). Для расширений смотрите директиву security.limit_extensions (по умолчанию разрешён только .php).
Проверить наличие файла и права по всей цепочке каталогов:
ls -l /var/www/site/index.php
namei -l /var/www/site/index.php

Проверить конфигурацию Nginx:
nginx -T
Особое внимание:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;

5. connect() to unix:/run/php/... failed

Пример в error.log Nginx:
connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory) while connecting to upstream

Что означает: Nginx не смог подключиться к PHP-FPM через Unix socket. Число в скобках (errno) сразу указывает на причину:
errno

Сообщение

Типичная причина

2No such file or directoryСокета нет: FPM не запущен или Nginx указывает не на тот сокет
13Permission deniedУ пользователя Nginx нет прав на сокет
111Connection refusedСокет есть, но никто его не слушает (FPM упал) или порт недоступен (для TCP)
11Resource temporarily unavailableПереполнена очередь listen.backlog: FPM не успевает принимать запросы
Проверить PHP-FPM и сокет:
systemctl status php8.3-fpm
ls -la /run/php/

Например, существует php8.3-fpm.sock, а Nginx настроен на php8.2-fpm.sock — соединение работать не будет.
Права на сокет задаются в пуле:
listen.owner = www-data
listen.group = www-data
listen.mode  = 0660
Пользователь, от которого работает Nginx, должен входить в эту группу или совпадать с владельцем.

6. 502 Bad Gateway

502 — это ошибка взаимодействия Nginx с upstream.
Если upstream — PHP-FPM, возможны:
  • PHP-FPM остановлен;
  • неправильный socket;
  • PHP-FPM завершился или worker упал во время запроса (SIGSEGV, SIGKILL);
  • проблемы с правами;
  • проблемы TCP-соединения;
  • переполнена очередь listen.backlog;
  • worker был завершён по request_terminate_timeout.
Сначала смотрим:
tail -n 100 /var/log/nginx/error.log
Затем:
systemctl status php8.3-fpmи:
journalctl -u php8.3-fpm -n 100
tail -n 100 /var/log/php8.3-fpm.log

Типичные сообщения Nginx при 502:
  • connect() ... failed (111: Connection refused) — FPM не слушает;
  • connect() ... failed (13: Permission denied) — нет прав на сокет;
  • connect() ... failed (2: No such file or directory) — нет сокета;
  • upstream prematurely closed connection while reading response header — worker умер или был убит во время запроса;
  • recv() failed (104: Connection reset by peer) — соединение сброшено на стороне FPM.
Сам 502 не показывает точную причину — её нужно искать в error.log Nginx и логах PHP-FPM.

7. 504 Gateway Timeout

504 означает, что Nginx не дождался ответа от upstream за установленное время.
В error.log это выглядит так:
upstream timed out (110: Connection timed out) while reading response header from upstream

Например:
Nginx
  ↓
PHP-FPM
  ↓
PHP
  ↓
MySQL
  ↓
долгий SQL-запрос
  ↓
PHP ждёт
  ↓
Nginx timeout
  ↓
504


Причиной может быть:
  • медленный PHP-код;
  • медленный SQL;
  • блокировка в БД;
  • внешний API;
  • занятые PHP-FPM workers;
  • слишком маленький timeout.
Поэтому 504 не означает автоматически проблему PHP-FPM.
Нужно определить, на каком этапе возникла задержка.

8. Maximum execution time exceeded

Пример:  
PHP Fatal error:  Maximum execution time of 30 seconds exceeded in /var/www/site/index.php on line 42

PHP-скрипт превысил установленное ограничение max_execution_time.
Важная особенность: на Linux этот лимит считает время, которое скрипт реально исполняет PHP-код (CPU-время). Время ожидания вне PHP не учитывается: ответ MySQL, сетевые вызовы к API, sleep(), системные вызовы. (На Windows считается реальное время.)
Поэтому типичные причины этой ошибки:
  • тяжёлые вычисления;
  • бесконечные или слишком долгие циклы;
  • обработка больших объёмов данных в памяти;
  • ошибка в приложении.
А вот долгий SQL-запрос или зависший внешний API чаще приводят не к этой ошибке, а к срабатыванию request_terminate_timeout (он считает реальное время) или к 504 от Nginx.
Здесь важно различать три разных ограничения:
PHP     → max_execution_time          (CPU-время скрипта, по умолчанию 30 с)
PHP-FPM → request_terminate_timeout   (реальное время запроса, по умолчанию 0 = выключен)
Nginx   → fastcgi_read_timeout        (ожидание ответа, по умолчанию 60 с)

9. request_terminate_timeout

В конфигурации пула PHP-FPM:
request_terminate_timeout = 60s
PHP-FPM завершит worker, если запрос выполняется дольше установленного реального времени. В логе это выглядит примерно так:
WARNING: [pool www] child 1234, script '/var/www/site/index.php' (request: "GET /index.php") execution timed out (61.2 sec), terminating

Клиент в этом случае обычно получает 502, потому что соединение закрывается без ответа.
Если запросы регулярно достигают этого значения, не стоит просто увеличивать timeout. Сначала необходимо выяснить: почему запрос выполняется 60 секунд?
PHP
 ↓
SQL-запрос
 ↓
ожидание БД
 ↓
worker занят
 ↓
другие workers заняты
 ↓
растёт очередь
 ↓
растёт время ответа


Главный инструмент для ответа на этот вопрос — slowlog. Он записывает stack trace запроса, который выполняется дольше указанного порога:
slowlog = /var/log/php8.3-fpm.slow.log
request_slowlog_timeout = 5s
В slowlog видно, на какой строке и в какой функции застрял скрипт: в SQL-вызове, в curl_exec, в обработке файла и так далее. (В контейнерах для записи slowlog может понадобиться capability SYS_PTRACE.)
Согласуйте таймауты между собой. Если fastcgi_read_timeout в Nginx меньше request_terminate_timeout, клиент получит 504, а worker будет ещё долго занят.

10. Too many open files

Пример:
Too many open files

Процесс достиг лимита открытых файловых дескрипторов.
Проверить лимит конкретного процесса:
cat /proc//limits
Найти PHP-FPM:
pgrep -a php-fpm
Проблема может быть связана с большим количеством:
  • файлов;
  • socket;
  • сетевых соединений;
  • параллельных запросов.
Лимит для FPM обычно поднимают в systemd-юните (LimitNOFILE=) или директивой rlimit_files в конфигурации пула. Это не специфическая ошибка PHP-FPM, но она может влиять на его работу.

11. listen queue

В PHP-FPM status можно увидеть:
listen queue: 5 - это количество запросов, ожидающих обработки.
Если очередь постоянно растёт, PHP-FPM не успевает обслуживать поступающие запросы.
Особенно важно смотреть одновременно:
active processes - количество PHP-FPM workers, которые прямо сейчас заняты обработкой запросов
idle processes -  количество workers, которые сейчас свободны и ждут новые запросы
max active processes - максимальное количество одновременно активных workers, которое было достигнуто с момента запуска PHP-FPM
listen queue -  количество запросов/соединений, которые сейчас ждут свободного PHP-FPM worker
max children reached -  сколько раз PHP-FPM достигал pm.max_children, то есть упирался в максимально разрешённое количество workers
slow requests - сколько запросов превысили request_slowlog_timeout (если он включён).
Например:
active processes: 20
idle processes: 0
max active processes: 20

Если при этом:
listen queue: 15 - это указывает, что запросы уже ожидают свободный worker.

Как включить status page

По умолчанию страница статуса отключена. В настройках пула:
pm.status_path = /status
В Nginx (доступ только с localhost, наружу статус открывать не стоит):
location = /status {
    allow 127.0.0.1;
    deny all;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
Проверка:
curl -s http://127.0.0.1/status
curl -s "http://127.0.0.1/status?full"    # подробно по каждому процессу

Основные настройки PHP-FPM

Обычно настройки пула находятся примерно здесь:
/etc/php/8.3/fpm/pool.d/www.conf
pm
Режим управления workers: 
pm = dynamic

Основные варианты:
static -  количество worker-процессов фиксированное.
dynamic -  количество процессов изменяется автоматически в заданных пределах.
ondemand - процессы создаются только тогда, когда появляются запросы.

pm.max_children
Максимальное количество одновременно работающих workers: 
pm.max_children = 50
Это не количество пользователей.
50 workers означает, что пул может одновременно выполнять до 50 PHP-запросов.
pm.start_servers
Для dynamic:
pm.start_servers = 5
Количество workers, создаваемых при запуске.
pm.min_spare_servers
Минимальное количество простаивающих workers:
pm.min_spare_servers = 5 
pm.max_spare_servers
Максимальное количество простаивающих workers: 
pm.max_spare_servers = 10
pm.max_requests
Например:
pm.max_requests = 500
После обработки указанного количества запросов worker будет перезапущен.
Это может быть полезно для ограничения накопления памяти процессом, например при утечках памяти в приложении или расширениях.

Как правильно диагностировать проблему

Не нужно сразу менять настройки PHP-FPM.
Используйте последовательность:
Проблема сайта
      ↓
Nginx error.log
      ↓
PHP-FPM log
      ↓
Статус PHP-FPM
      ↓
Workers / queue
      ↓
RAM / CPU / Disk
      ↓
PHP-код / БД / API
      ↓
Исправление
      ↓
Повторная проверка


1. Проверяем PHP-FPM
systemctl status php8.3-fpm
2. Смотрим ошибки
journalctl -u php8.3-fpm -n 100
3. Смотрим Nginx
tail -n 100 /var/log/nginx/error.log
4. Проверяем RAM
free -h
5. Проверяем workers
ps aux | grep '[p]hp-fpm'
6. Проверяем CPU
top
7. При необходимости проверяем диск
iostat -xz 1

Быстрая таблица ошибок

Сообщение

Что означает

Что проверить

max_childrenВсе workers занятыWorkers, RAM, нагрузку
seems busyWorkers занятыЧастоту и длительность нагрузки
SIGKILLПроцесс принудительно завершёнOOM, RAM
Primary script unknownPHP-FPM не нашёл скриптroot, SCRIPT_FILENAME, файл
connect() ... failedNginx не подключился к PHP-FPMService, socket, права
502Nginx не получил нормальный ответ upstreamNginx + PHP-FPM logs
504Ответ от upstream не пришёл вовремяPHP, БД, API, workers, timeout
Maximum execution timePHP превысил лимит выполненияPHP-код, БД, API
request_terminate_timeoutPHP-FPM завершил слишком долгий запросПричину длительного запроса
Too many open filesДостигнут лимит дескрипторовlimits, sockets, files
listen queueЗапросы ждут workerWorkers и pm.max_children

Главное

PHP-FPM-проблему нельзя диагностировать только по коду ошибки.
Например:
502— это симптом.
А connect() to unix:/run/php/php8.3-fpm.sock failed— уже конкретная информация о проблеме соединения.
Или:
server reached pm.max_children говорит, что workers закончились, но не объясняет, почему они заняты.
Поэтому правильный подход:
Симптом
  ↓
Лог
  ↓
Конкретная причина
  ↓
Проверка ресурсов
  ↓
Исправление
  ↓
Повторный тест

Именно такой подход позволяет не просто убрать ошибку 502/504, а найти реальную причину проблемы — будь то PHP-FPM, PHP-код, база данных, память, диск или внешнее соединение.

Премиум выделенные серверы

Смотреть конфигурации