php-fpm в systemd: почему не запускается и падает
php-fpm в systemd отвечает за пул рабочих процессов, и почти все его проблемы делятся на три группы: ошибка в описании пула (служба не стартует), права на unix-сокет (веб-сервер получает отказ), исчерпание рабочих процессов (сайт отвечает медленно или не отвечает).
О службе
Имя unit включает версию PHP: php8.3-fpm.service, php8.1-fpm.service и так далее. После обновления PHP на сервере остаются несколько unit одновременно, и типичная ошибка — перезапускать не тот. Проверять всегда стоит, какая версия действительно включена и какой сокет использует веб-сервер.
Сокет пула описывается в его файле настроек (/etc/php/8.3/fpm/pool.d/www.conf), а не в unit-файле: там задаются путь, владелец и права. Именно поэтому ошибки доступа к сокету решаются правкой описания пула, а не unit-файла. Веб-сервер должен иметь право писать в этот сокет — обычно через общую группу.
Исчерпание рабочих процессов выглядит не как отказ службы: она остаётся активной, а запросы выстраиваются в очередь. В журнале при этом появляется предупреждение о достижении максимума дочерних процессов, и это единственный ранний признак.
Как устроена
| Имя unit | зависит от версии: php8.3-fpm.service, php8.1-fpm.service |
|---|---|
| Проверка настроек | php-fpm8.3 -t — разбирает и основной файл, и описания пулов |
| Где описан сокет | в файле пула (pool.d/*.conf), параметры listen, listen.owner, listen.group, listen.mode |
| Тип unit | Type=notify — php-fpm умеет сообщать systemd о готовности |
| Перезагрузка настроек | systemctl reload php8.3-fpm — корректная замена рабочих процессов |
Частые ошибки
25 записей базы отмечены за этой службой.
Сообщения журнала
- Permission denied в журнале службыОтказ в доступе у службы systemd: права на файл, каталоги по пути, пользователь службы, параметры изоляции, SELinux и AppArmor.
- Address already in use при запуске службыПорт или адрес уже занят: bind() failed (98: Address already in use). Как найти владельца порта и что делать с остатками прежнего процесса.
- Connection refused в журнале службыСоединение отклонено: служба не может подключиться к базе, кешу или другому сервису. Порядок запуска, адрес, брандмауэр.
Коды выхода
- status=1/FAILURE в systemdКод 1/FAILURE означает, что программа запустилась и сама завершилась с ошибкой. Как найти настоящую причину в журнале службы.
- status=233/RUNTIME_DIRECTORY в systemdКод 233/RUNTIME_DIRECTORY: не удалось подготовить каталог службы в /run из RuntimeDirectory=. Права, режим, удаление при остановке.
- status=200/CHDIR в systemdКод 200/CHDIR означает, что systemd не смог перейти в каталог из WorkingDirectory= до запуска программы. Причины и решение.
- status=203/EXEC в systemdКод 203/EXEC означает, что systemd не смог выполнить программу из ExecStart=. Разбор причин: путь, права, интерпретатор, синтаксис оболочки.
Состояния результата
- start-limit-hit: служба заблокирована после серии перезапусковСостояние start-limit-hit и сообщение start request repeated too quickly: systemd перестал перезапускать службу. Как разблокировать и найти исходную причину.
- Failed with result 'core-dump'Состояние core-dump: процесс службы аварийно завершился и сохранил дамп памяти. Как открыть дамп и прочитать трассировку.
Ресурсы и ограничения
- Too many tasks: упор в предел TasksMaxСлужба не может создать новый процесс: достигнут предел TasksMax. Где он задан и как поднять правильно.
- Too many open files в журнале службыСлужба исчерпала лимит файловых дескрипторов. Как правильно поднять LimitNOFILE и когда дело в утечке.
- Служба не создаёт потоки: упор в пределОшибка создания потока: исчерпан TasksMax или системный предел процессов. Как посчитать нужное значение.
Сигналы
- signal=SEGV (status=11/SEGV) в systemdПроцесс службы завершён сигналом SEGV: обращение к недопустимой памяти. Как собрать дамп и что смотреть.
- signal=INT и signal=QUIT в systemdПроцесс службы завершён сигналом INT или QUIT. Кто их посылает службам и почему это обычно не systemd.
Ошибки служб
- Apache: конфликт модулей многопроцессности и PHPApache не запускается после включения модуля PHP: несовместимость с выбранным модулем многопроцессности.
- nginx 413 Request Entity Too LargeЗагрузка файла отклонена: превышен client_max_body_size. Где менять и что ещё ограничивает размер.
- nginx 502 Bad Gateway: connect() failed к приложениюnginx работает, а приложение недоступно: connect() failed, connection refused, no such file or directory для сокета. Разбор 502.
- nginx 504 Gateway Time-out: upstream timed outnginx не дождался ответа приложения. Разбор таймаутов proxy_read_timeout и fastcgi_read_timeout, поиск медленных мест.
- php-fpm отдаёт старый код после выкладкиПосле обновления файлов сайт показывает прежнюю версию: кеш скомпилированного кода не сброшен.
- php-fpm: Allowed memory size exhaustedСкрипт исчерпал предел памяти PHP: ошибка 500, оборванные запросы. Где менять предел и когда он спасает.
- php-fpm: server reached pm.max_children settingПул php-fpm исчерпал рабочие процессы: сайт отвечает медленно или отдаёт 502. Как считать pm.max_children.
- php-fpm: ошибка в описании пула и отказ запускаphp-fpm не запускается: неверный параметр в pool.d, несуществующий пользователь, недоступный путь сокета.
- Веб-сервер не соединяется с обработчиком PHPОтвет 502 при работающем обработчике: веб-сервер и обработчик используют разные способы связи.
- Фоновые задания веб-приложения не выполняютсяЗадания по расписанию не идут: неверный пользователь, не тот интерпретатор или задача не включена.
Таймеры, сокеты, монтирование
- Служба не получает сокет при сокет-активацииСокет активен, служба запускается, но не находит переданный дескриптор. Разбор: Accept, FileDescriptorName, соответствие имён.
Коды выхода этой службы
Числа в status=N ниже 200 назначает сама программа, 200 и выше — systemd, когда не смог подготовить запуск.
Диагностика
Проверка настроек: печатает файл и строку с ошибкой в описании пула.
sudo php-fpm8.3 -tСостояние службы и последние строки журнала.
systemctl status php8.3-fpm --no-pager -lПредупреждения о достижении максимума рабочих процессов и о падениях дочерних.
journalctl -u php8.3-fpm -n 50 --no-pager | grep -iE "warning|error|child"Существует ли unix-сокет пула и по какому пути.
sudo ss -xln | grep phpМожет ли веб-сервер писать в сокет: главная проверка при ошибке шлюза.
sudo -u www-data test -w /run/php/php8.3-fpm.sock && echo доступ есть || echo отказПараметры unit, которые тут важны
- Type=notify: php-fpm сообщает о готовности сам
- ExecReload=перезагрузка сигналом USR2 — рабочие процессы заменяются мягко
- RuntimeDirectory=каталог в /run для сокета и pid-файла
- TasksMax=пул рабочих процессов упирается в предел задач при большом pm.max_children
Частые вопросы
nginx отдаёт 502, php-fpm при этом активен. Что смотреть?
Сначала путь к сокету: он должен совпадать в nginx и в описании пула. Затем права на сокет для пользователя веб-сервера. И только потом — журнал php-fpm на предмет падений рабочих процессов.
Источники
- Документация PHP: FPM и настройка пулов
- systemd.service(5)
- Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)