BitrixVM PHP код не выполняется: основные причины
Когда в браузере вместо страницы отображается исходный PHP-код — это классический симптом разрыва связки Nginx + PHP-FPM. В наших проектах такая ситуация возникает обычно после обновления BitrixVM, миграции на новый сервер или при неосторожной правке конфигов руками. Клиент видит голый текст <?php и пустые белые страницы — бизнес-критичная проблема, которую нужно решать в первую очередь. Мы регулярно сталкиваемся с этим у магазинов с высоконагруженным каталогом, где каждая минута простоя стоит денег. Основные причины сводятся к пяти сценариям: демон PHP-FPM не запущен, Nginx не знает, что .php нужно отдавать в обработку, путь к сокету в конфигах не совпадает с реальным, пул PHP-FPM сконфигурирован с ошибкой, или серверу просто не хватает ресурсов, памяти и дочерних процессов.
- PHP-FPM не запущен, мастер-процесс упал после перегрузки памяти или не стартовал при перезапуске сервисов. Проверяется командой
systemctl status php-fpm. - Nginx не передаёт .php в PHP-FPM, отсутствует или закомментирован блок
location ~ \.php$в конфиге виртуального хоста. Nginx отдаёт файл как статику. - Неверный путь к сокету, в
fastcgi_passуказан unix-сокет, который не совпадает сlistenв пуле PHP-FPM. Типичная ошибка после смены версии PHP. - Ошибки в конфигурации пула или синтаксическая ошибка в файлах
/etc/php-fpm.d/могут помешать запуску пула. Подробности следует искать в логахphp-fpm.log. - Недостаточно памяти/процессов, пул исчерпал лимит
pm.max_children, новые запросы встают в очередь или падают с 502/504.
Понимание архитектуры BitrixVM здесь критично. Связка стандартная: Nginx принимает HTTP-запросы, статику отдаёт сам, а .php-файлы передаёт в PHP-FPM через unix-сокет. Если Nginx по какой-то причине не видит в запросе .php или не может соединиться с сокетом, он честно отдаёт файл как есть, то есть в виде исходного кода. Типовая структура конфигов в BitrixVM: основные настройки Nginx лежат в /etc/nginx/bx/site_avaliable/, а пулы PHP-FPM настраиваются в соответствующих конфигурационных файлах (например, в каталоге /etc/php-fpm.d/). Мы обычно начинаем диагностику с проверки fastcgi_pass в конфиге сайта: там должен быть путь к сокету, совпадающий с listen в пуле. Об этом подробнее, в следующих секциях.
BitrixVM показывает исходный код: проверка состояния PHP-FPM
Самый частый запрос на эту тему — «сделал всё по инструкции, а в браузере по-прежнему голый PHP-код». В нашей практике примерно каждый второй случай отображения исходного кода на BitrixVM решается простой проверкой: жив ли PHP-FPM. Дело в том, что BitrixVM — это связка Nginx + PHP-FPM, и если второй компонент упал, Nginx честно отдаёт файл как есть, не понимая, что его нужно обработать. Типичный сценарий: после обновления пакетов, смены версии PHP или перезагрузки сервера демон PHP-FPM не стартует автоматически. Мы регулярно видим это у клиентов, которые обновляли BitrixVM через штатное меню окружения (1. Manage servers in the pool → 4. Update packages on host), процесс обновления сбрасывает автозапуск некоторых сервисов. Поэтому первым делом смотрим статус.
# Проверка статуса PHP-FPM
systemctl status php-fpm
# Альтернативная проверка — поиск процессов
ps aux | grep php-fpm- Выполнить
systemctl status php-fpm, если вы видитеactive (running), PHP-FPM работает. Статусinactive (dead)илиfailed, причина найдена. - Если сервис неактивен, запустить его:
systemctl start php-fpm. После запуска проверьте статус повторно, он должен смениться наactive. - Включить автозапуск, чтобы PHP-FPM стартовал при перезагрузке сервера:
systemctl enable php-fpm. - Проверить, что сокет существует и доступен:
grep -r '^listen' /etc/php-fpm.d/ # путь к сокету смотрим в конфиге пула, затем ls -la по нему. Если файла нет, PHP-FPM не смог создать сокет, проверьте логи:journalctl -u php-fpm --no-pager | tail -30.
BitrixVM 9.0.9 ошибка: настройка PHP-FPM для корректной работы
Распространённая ошибка: BitrixVM 9.0.9 стоит, PHP-FPM запущен, но в браузере — пустая страница или 502 Bad Gateway. Чаще всего причина не в том, что сервис упал, а в том, что пул настроен неправильно. В нашей практике это регулярно всплывает после обновления с более старых версий виртуальной машины — когда конфигурация пула остаётся «как была», а версия PHP и требования к ресурсам изменились. Стандартные настройки из коробки в BitrixVM 9.0.9 рассчитаны на минимальную нагрузку: один-два сайта с парой десятков посетителей. Если у вас магазин с активным каталогом или несколько проектов на одной машине, эти параметры гарантированно приведут к тому, что PHP-воркеры будут заканчиваться, а Nginx, отдавать ошибки вместо страниц. Поэтому после базовой проверки состояния сервиса (о ней ниже) мы всегда идём в конфигурацию пула.
Параметры пула pm.max_children и pm.start_servers
Главный параметр, который определяет, сколько PHP-воркеров одновременно может обрабатывать запросы, pm.max_children. В официальной документации «1С-Битрикс» указано, что настройки «по умолчанию» — это далеко не всегда хорошо, и их неграмотное изменение может дать обратный результат. Для одного сайта-визитки стандартных значений может хватить, но для магазина с 50–100 одновременными посетителями их, скорее всего, будет недостаточно. Мы в таких случаях поднимаем до 20–30, но только после расчёта по памяти: один воркер PHP 8.2 в среднем съедает 30–40 МБ. Если на сервере 2 ГБ ОЗУ, ставить 50 детей — значит гарантированно убить swap.
Второй важный параметр, pm.start_servers. Это количество воркеров, которые поднимаются сразу при старте PHP-FPM. Если поставить слишком мало (проверьте текущее значение в вашем www.conf), первые секунды после перезапуска сервиса все запросы будут ждать, пока пул «прогреется». Мы обычно ставим pm.start_servers = 4 при pm.max_children = 20, а pm.min_spare_servers и pm.max_spare_servers, 4 и 8 соответственно. Это даёт плавный старт без пиков.
# /etc/php/8.2/fpm/pool.d/www.conf — BitrixVM 9.0.9
; Динамический менеджер процессов (рекомендуется для большинства проектов)
pm = dynamic
; Максимум детей — считайте по формуле: (RAM - резерв) / 40 МБ
pm.max_children = 20
; Стартовое количество воркеров
pm.start_servers = 4
; Минимум свободных воркеров (чтобы не ждать создания)
pm.min_spare_servers = 4
; Максимум свободных (чтобы не держать лишних)
pm.max_spare_servers = 8Проверка прав доступа к сокету и listen.mode
Даже если пул настроен идеально, но сокет PHP-FPM недоступен для чтения и записи пользователю веб-сервера, соединения не будет. Стандартная ошибка: сокет создаётся с правами 0660 и владельцем, соответствующим пользователю мастер-процесса PHP-FPM (в BitrixVM — bitrix; www-data встречается в Debian-системах), а Nginx в BitrixVM может работать от другого пользователя (например, bitrix или nginx). В итоге, Permission denied в логах Nginx и 502 Bad Gateway на сайте.
Проверить это просто: смотрим, кто владелец сокета и какие права выставлены. Если владелец не совпадает с пользователем Nginx, нужно либо сменить владельца через listen.owner и listen.group в конфигурации пула, либо выставить listen.mode = 0666. Второе, временное решение, но для диагностики подходит.
# Проверяем текущие права и владельца сокета
ls -la /var/run/php-fpm/php-fpm.sock
# Временное решение — дать доступ всем (ТОЛЬКО для диагностики!)
sudo chmod 666 /var/run/php-fpm/php-fpm.sock
# Правильное решение — настроить владельца в пуле
# В /etc/php/8.2/fpm/pool.d/www.conf:
# listen.owner = nginx
# listen.group = nginx
# listen.mode = 0660PHP не обрабатывается BitrixVM: проверка конфигурации Nginx
Типичный сценарий: systemctl status php-fpm показывает active (running), пул BitrixVM настроен, а в браузере — всё тот же исходный PHP-код. Значит, проблема не в самом интерпретаторе, а в том, что Nginx не передаёт ему запросы к .php-файлам. В нашей практике это второй по частоте случай после остановленного PHP-FPM. Проверка конфигурации Nginx — обязательный шаг, когда базовые проверки пройдены, а симптом остался. Если не разобраться здесь, можно потратить часы на переустановку пакетов, которые и так работают.
Проверка location ~ \.php$ в конфиге хоста
Nginx обрабатывает PHP-запросы через специальный блок location ~ \.php$. Если он отсутствует, отсутствует или закомментирован, все запросы к .php будут отдаваться как статические файлы, то есть исходным кодом. В BitrixVM этот блок по умолчанию находится в файле конфигурации вашего сайта, обычно /etc/nginx/bx/site_enabled/ваш_сайт.conf. Откройте его и убедитесь, что секция присутствует и не закомментирована символом #.
# Пример корректного блока location для обработки PHP в Nginx
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}Проверка fastcgi_pass: сокет или TCP?
Даже если блок location ~ \.php$ на месте, запросы могут не доходить до PHP-FPM из-за неверного адреса в директиве fastcgi_pass. В BitrixVM по умолчанию используется UNIX-сокет, это быстрее и безопаснее, чем TCP-соединение через localhost. Однако после обновлений или ручной правки конфигов адрес может сбиться. Проверьте, совпадает ли путь в fastcgi_pass с тем, что указан в пуле PHP-FPM (обычно в /etc/php-fpm.d/www.conf).
# Команда для поиска fastcgi_pass в конфигах
grep -r 'fastcgi_pass' /etc/nginx/Разница между сокетом и TCP, не только в производительности. UNIX-сокет (например, unix:/tmp/php-fpm.sock — так в BitrixVM, или unix:/var/run/php-fpm/php-fpm.sock в типовом CentOS) работает только между процессами на одном сервере, исключая лишние сетевые накладные расходы. TCP (например, 127.0.0.1:9000) нужен, если PHP-FPM и Nginx находятся на разных хостах, но в стандартной BitrixVM это избыточно. Мы в проектах всегда оставляем сокет, он быстрее и проще в диагностике: если сокет-файл существует и доступен для чтения Nginx, значит, связка работает.
Настройка PHP-FPM BitrixVM: оптимизация пула и устранение ошибок
После того как базовая проблема решена, стоит оптимизировать пул PHP-FPM для производительности. BitrixVM поставляется с консервативными настройками — в расчёте на то, что администратор их подгонит под свой проект. В нашей практике это одна из первых задач, которую мы решаем на этапе приёмки сервера: дефолтный пул рассчитан на небольшое число одновременных процессов, что для магазина с каталогом на 30 тысяч товаров и 300 посетителями в пике — гарантированный простой. Клиенты приходят с жалобами на «тормоза» в админке и медленную выдачу товарных карточек, а причина часто именно в том, что пул упирается в лимит pm.max_children. Оптимизация пула даёт прямой прирост скорости без изменения кода, только правка конфигурации. Эта настройка комбинируется с предыдущей проверкой pm.status_path и корректировкой таймаутов Nginx, о которых мы говорили выше.
Настройка pm.max_children под нагрузку
Главный параметр, который определяет, сколько PHP-процессов сможет работать одновременно. Если поставить слишком мало, запросы будут вставать в очередь, пользователи увидят «задумчивый» сайт. Если слишком много, сервер уйдёт в своп и упадёт. У нас в проектах мы подбираем pm.max_children под реальную пиковую нагрузку: смотрим логи php-fpm через pm.status_path, замеряем active processes в час пик и добавляем запас 20–30%. Для типового магазина на BitrixVM с 2–4 ГБ ОЗУ рабочий диапазон, 20–40 процессов. Если сайт отдаёт статику через CDN, а PHP-нагрузка идёт только на динамические страницы, можно ставить ближе к нижней границе.
Формула расчёта: (память сервера / память на один PHP-процесс). Память на один процесс в BitrixVM обычно 30–50 МБ (замеряем через ps aux | grep php-fpm). Пример для сервера с 4 ГБ ОЗУ: 4096 МБ / 40 МБ ≈ 102 процесса. Но это теоретический максимум, на практике мы не поднимаем выше 40–50, оставляя память для MySQL, Nginx и самого Bitrix. Если на сервере крутится ещё и Elasticsearch, запас нужно увеличить. Важно помнить: pm.max_children, это не количество воркеров, которые работают постоянно, а максимум одновременно запущенных. При pm = dynamic PHP-FPM сам регулирует количество в пределах от pm.min_spare_servers до pm.max_children.
Настройка pm.max_requests для предотвращения утечек
Второй критичный параметр, pm.max_requests. Он задаёт, сколько запросов обработает один PHP-процесс, прежде чем будет перезапущен. Утечки памяти в PHP-расширениях или в самом Bitrix, не редкость, особенно если используются тяжёлые модули вроде imagemagick или curl с длинными сессиями. Без лимита процесс со временем «раздувается» до сотен мегабайт, и пул начинает потреблять всю доступную память. В наших проектах мы ставим pm.max_requests = 500, это баланс между стабильностью и производительностью. Если сайт использует кеширование и редко генерирует динамику, можно поднять до 1000–2000. Для высоконагруженных магазинов с частыми обменами с 1С, 300–500 оптимально.
cat /etc/php-fpm.d/*.conf # имя файла пула зависит от версии окружения
[bitrix]
pm = dynamic
pm.max_children = 40
pm.start_servers = 8
pm.min_spare_servers = 4
pm.max_spare_servers = 16
pm.max_requests = 500Частые вопросы
Можно ли использовать PHP-FPM с другим пользователем, кроме bitrix, и не сломает ли это права доступа?
Да, можно, но тогда в пуле PHP-FPM (например, в /etc/php-fpm.d/www.conf) нужно явно указать user и group нового пользователя, а также скорректировать права на папки /home/bitrix и /tmp/php-upload, иначе BitrixVM не сможет записывать кеш и временные файлы.
Что делать, если после настройки PHP-FPM сайт открывается, но скачивается файл index.php вместо страницы?
Проверьте, что в location ~ \.php$ в конфиге Nginx указан fastcgi_pass на unix-сокет (например, unix:/var/run/php-fpm/php-fpm.sock), а не на localhost:9000, и что директива try_files не переопределяет обработку PHP-файлов.
А если у меня BitrixVM 9.0.9, но PHP-FPM не стартует с ошибкой «ERROR: unable to bind listening socket»?
Это значит, что сокет или порт уже занят — проверьте, не запущен ли второй экземпляр PHP-FPM, и удалите старый sock-файл в /var/run/php-fpm/ перед перезапуском службы.
Чем отличается настройка обработчика .php через location ~ \.php$ от использования map $uri в Nginx?
location ~ \.php$ — это прямой блок для передачи всех PHP-запросов в PHP-FPM, а map $uri используется для динамического выбора бэкенда или пула в зависимости от URI; для типовой BitrixVM достаточно первого варианта без map.
Можно ли отключить проверку прав доступа к сокету PHP-FPM, чтобы не настраивать listen.mode?
Нет, отключать проверку нельзя — это снизит безопасность. Вместо этого установите listen.mode = 0660 в пуле и добавьте пользователя nginx в группу, владеющую сокетом (обычно group = nginx).