Основные ошибки 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 = 5050 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 -h4. 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) в один из каталогов по пути к файлу.
Проверить наличие файла и права по всей цепочке каталогов:
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 | Сообщение | Типичная причина |
| 2 | No such file or directory | Сокета нет: FPM не запущен или Nginx указывает не на тот сокет |
| 13 | Permission denied | У пользователя Nginx нет прав на сокет |
| 111 | Connection refused | Сокет есть, но никто его не слушает (FPM упал) или порт недоступен (для TCP) |
| 11 | Resource temporarily unavailable | Переполнена очередь listen.backlog: FPM не успевает принимать запросы |
systemctl status php8.3-fpm
ls -la /run/php/Например, существует php8.3-fpm.sock, а Nginx настроен на php8.2-fpm.sock — соединение работать не будет.
Права на сокет задаются в пуле:
listen.owner = www-dataПользователь, от которого работает Nginx, должен входить в эту группу или совпадать с владельцем.
listen.group = www-data
listen.mode = 0660
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.
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.
Нужно определить, на каком этапе возникла задержка.
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 считается реальное время.)
Поэтому типичные причины этой ошибки:
- тяжёлые вычисления;
- бесконечные или слишком долгие циклы;
- обработка больших объёмов данных в памяти;
- ошибка в приложении.
Здесь важно различать три разных ограничения:
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 = 60sPHP-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В slowlog видно, на какой строке и в какой функции застрял скрипт: в SQL-вызове, в curl_exec, в обработке файла и так далее. (В контейнерах для записи slowlog может понадобиться capability SYS_PTRACE.)
request_slowlog_timeout = 5s
Согласуйте таймауты между собой. Если 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;
- сетевых соединений;
- параллельных запросов.
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.confpm
Режим управления 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 = 5pm.max_spare_servers
Максимальное количество простаивающих workers:
pm.max_spare_servers = 10pm.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-fpm2. Смотрим ошибки
journalctl -u php8.3-fpm -n 1003. Смотрим Nginx
tail -n 100 /var/log/nginx/error.log4. Проверяем RAM
free -h5. Проверяем workers
ps aux | grep '[p]hp-fpm'6. Проверяем CPU
top7. При необходимости проверяем диск
iostat -xz 1Быстрая таблица ошибок
Сообщение | Что означает | Что проверить |
| max_children | Все workers заняты | Workers, RAM, нагрузку |
| seems busy | Workers заняты | Частоту и длительность нагрузки |
| SIGKILL | Процесс принудительно завершён | OOM, RAM |
| Primary script unknown | PHP-FPM не нашёл скрипт | root, SCRIPT_FILENAME, файл |
| connect() ... failed | Nginx не подключился к PHP-FPM | Service, socket, права |
| 502 | Nginx не получил нормальный ответ upstream | Nginx + PHP-FPM logs |
| 504 | Ответ от upstream не пришёл вовремя | PHP, БД, API, workers, timeout |
| Maximum execution time | PHP превысил лимит выполнения | PHP-код, БД, API |
| request_terminate_timeout | PHP-FPM завершил слишком долгий запрос | Причину длительного запроса |
| Too many open files | Достигнут лимит дескрипторов | limits, sockets, files |
| listen queue | Запросы ждут worker | Workers и 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-код, база данных, память, диск или внешнее соединение.