Короткий ответ

Сайт на site.example отдаёт статику, а PHP — 502 или «скачать .php»: смотрите FPM, не nginx -t. Три оси: unit php8.3-fpm/php8.2-fpm active, пул www слушает тот же unix/TCP, что fastcgi_pass, лимиты pm.max_children не исчерпаны. Корень /var/www/site.example, IP 10.0.20.40. CLI php -v не доказывает, что пул жив.

Если unit failed — journalctl -u php8.3-fpm и php-fpm8.3 -t. Если unit active, а сокета нет — другой listen или другой major 8.2 vs 8.3.

Симптомы и как отличить

  • systemctl is-active php8.3-fpm = failed.
  • ls /run/php/ пуст или только php8.2-fpm.sock.
  • В логе FPM: WARNING: [pool www] server reached pm.max_children.
  • Nginx: 502; Apache: AH01079: failed to make connection to backend.
СостояниеСтатья
FPM мёртв, 502эта + 502
FPM жив, Fatal 500500
FPM жив, очередь, медленномедленно
Таймаут 60с504

Возможные причины

  1. Пакет не установлен / unit disabled после миграции.
  2. Синтаксис www.conf: дубль listen, неверный user.
  3. Сокет в /run/php/ не создаётся — нет каталога, PrivateTmp, полный диск.
  4. pm = dynamic при слишком большом pm.start_servers относительно RAM — fork не проходит, unit падает.
  5. pm.max_children мал: все воркеры заняты, новые запросы ждут/502.
  6. listen.acl vs права nginx.
  7. После apt: sock сменил имя.
  8. Pool файл в pool.d с listen = 127.0.0.1:9000, firewall не при чём — nginx ходит в unix.

Диагностика

1. Unit и тест конфига FPM

systemctl status php8.3-fpm php8.2-fpm --no-pager
sudo php-fpm8.3 -t
sudo journalctl -u php8.3-fpm -n 80 --no-pager
df -h / /run

php-fpm8.3 -t должен сказать test is successful и путь конфига /etc/php/8.3/fpm/php-fpm.conf.

2. Пул и listen

sudo grep -E '^\[|^listen|^user|^group|^pm' /etc/php/8.3/fpm/pool.d/www.conf
ls -l /run/php/
sudo ss -xl | grep php
sudo ss -tlnp | grep -E 'php-fpm|:9000'

3. Согласование с фронтом

sudo grep -R fastcgi_pass /etc/nginx/sites-enabled
sudo grep -R php-fpm /etc/apache2/conf-enabled /etc/apache2/sites-enabled 2>/dev/null

4. Лимиты pm и текущая нагрузка

sudo grep -E '^pm' /etc/php/8.3/fpm/pool.d/www.conf
# статус пула, если включили pm.status_path
curl -s http://127.0.0.1/fpm-status
ps -C php-fpm8.3 -o pid,user,rss,stat,cmd | head

pm.status_path открывайте только с localhost/allow 127.0.0.1.

5. RAM

free -m
ps -C php-fpm8.3 -o rss= | awk '{s+=$1} END {print s/1024 " MiB RSS sum"}'

max_children * средний RSS не должен превышать доступную RAM минус MySQL/nginx.

Решение

sudo cp -a /etc/php/8.3/fpm/pool.d/www.conf /root/www.conf.$(date +%F)

Сценарий A. Unit не установлен / не запущен

dpkg -l php8.3-fpm php8.2-fpm | grep ^ii
sudo apt-get install -y php8.3-fpm php8.3-mysql php8.3-xml php8.3-curl php8.3-mbstring
sudo systemctl enable --now php8.3-fpm

Набор расширений — по фактическому composer/плагинам, не копируйте «все php-*».

Сценарий B. Неверный listen

Канон Ubuntu:

[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
sudo systemctl restart php8.3-fpm
ls -l /run/php/php8.3-fpm.sock

В nginx — тот же unix. Не chmod 777 на сокет.

Сценарий C. max_children

Симптом: сайт «встаёт» под ботами/пиком, в логе max_children, процессы есть. Поднимите pm.max_children после расчёта RAM. Параллельно режьте ботов: боты.

Пример: RSS воркера ~80 МиБ, 2 ГиБ под PHP → около 20 children, не 100.

Сценарий D. Unit failed на старте

Часто: www.conf с pm.start_servers = 50 при max_children = 10 — FPM отказывается стартовать. Исправьте неравенства:

pm.min_spare ≤ start ≤ max_spare ≤ max_children.

Полный /run — чистка чужих pid, не отключение tmpfs.

Сценарий E. Apache proxy_fcgi

<FilesMatch ".+\.php$">
    SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>

После смены сокета systemctl reload apache2. Configtest: Apache.

Сценарий F. Несколько сайтов — отдельные пулы

Для второго vhost не копируйте [www] дважды в один www.conf. Создайте /etc/php/8.3/fpm/pool.d/site.example.conf с [site_example], другим listen сокетом и при необходимости другим user. В nginx — этот сокет. Иначе pm.max_children общие, один сайт душит другой.

На 24.04 каталог /run/php/ создаёт пакет; не делайте listen = /tmp/php.sock — после reboot и PrivateTmp сокет «пропадёт». Оставьте /run/php/php8.3-fpm.sock.

php-fpm8.3 -t после правки обязателен: опечатка pm.max_childrens (лишняя s) не стартует пул, nginx даёт 502, CLI php -v зелёный.

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

systemctl is-active php8.3-fpm
ls -l /run/php/php8.3-fpm.sock
echo '<?php echo php_sapi_name();' | sudo tee /var/www/site.example/fpm-probe.php >/dev/null
curl -s --resolve site.example:80:10.0.20.40 http://site.example/fpm-probe.php
sudo rm /var/www/site.example/fpm-probe.php

Ожидание: fpm-fcgi, не cli. Удалите зонд сразу. Главная / должна открывать PHP, не скачивать файл.

Если не помогло

  • Сокет есть, 502: права, другой root namespace (контейнер).
  • FPM active, PHP не парсит: security.limit_extensions, файл без .php.
  • Два пула www и site — vhost может ходить не туда.
  • OOM: journalctl -k | grep php-fpm, уменьшите children.
  • После apt upgrade unit php8.3-fpm active, а nginx всё ещё в php8.2-fpm.sock — это не «FPM сломан», это рассинхрон путей. Сверьте ls /run/php и fastcgi_pass одним diff.

Профилактика

  • Мониторинг unit + число процессов + max_children warning в логе.
  • Документировать major PHP на стенде.
  • Не менять listen в одном месте из трёх (пул, nginx, apache).

FAQ

reload или restart FPM?

Смена listen/сокета — restart. Смена php.ini и max_children — обычно reload. Если сомневаетесь и нет длинных запросов — restart в окно.

pm = static лучше?

Предсказуемее по RAM. dynamic экономит ночью. На маленьких VPS static с малым N проще считать.

Нужен ли отдельный пул на сайт?

Да, если разные user или лимиты. Для одного site.example достаточно www.

PHP-FPM слушает 0.0.0.0:9000

Закройте. Только unix или 127.0.0.1. Иначе FPM торчит в сеть.

После апгрейда 8.2→8.3 сайт старый

Включён php8.2-fpm, nginx не переведён. Переключите sock и расширения пакетов 8.3.