Как понять, что держит PHP-процесс в BitrixVM: разбор PID без боли
Практический разбор, как найти зависший PHP-процесс в BitrixVM на CentOS: pstree, ps, lsof, strace и htop. Без перезапусков и гаданий.
Требования
- 1C-Битрикс: Виртуальная машина
- Доступ к серверу
- Базовое понимание процессов Linux
Как понять, что держит PHP-процесс в BitrixVM
Проблема и контекст
Ситуация типовая для продакшена на 1C-Битрикс:
- сервер жив, load есть;
- сайт то отвечает, то нет;
- cron выполняется странно или вообще «залип»;
- в
htopвисит PHP-процесс по 10–30 минут; - перезапускать сервисы нельзя или не хочется.
Вопрос звучит просто: что конкретно делает этот процесс и почему он не заканчивается?
Перезапуск PHP-FPM или Apache — крайняя мера. До неё почти всегда можно понять причину.

Окружение
Разбор актуален для стандартной BitrixVM:
- CentOS
- Percona Server 8.0 (MySQL)
- Apache 2.4.x
- PHP 8.x
- Nginx 1.26.x
- Redis
- Memcached
Никаких sudo — работаем из-под root, как это обычно и бывает на VM.
Общая логика анализа
Я всегда иду по одному и тому же маршруту:
- Найти конкретный PID
- Посмотреть дерево процессов
- Понять, какие ресурсы он держит
- Проверить, на чём он реально завис
- Только потом принимать решение
Ниже — по шагам.
Шаг 1. Берём один PID и смотрим дерево
Допустим, в htop увидели подозрительный PHP-процесс.
PID=<один_pid_php>
Дерево процессов
pstree -ap $PID
Что даёт команда:
- показывает, кто породил процесс;
- сразу видно, это
cron,php,apacheилиphp-fpm; - полезно для понимания контекста (агент, CLI, веб).
Часто здесь уже видно что-то вроде:
cron---php---php
И становится понятно, что это не веб-запрос, а фоновая задача.
Детали процесса
ps -o pid,ppid,etime,stat,cmd -p $PID
Разбор полей:
- etime — сколько времени процесс живёт
- stat — состояние (
R,S,D) - cmd — команда запуска (очень важно)
Если etime — десятки минут, а cmd указывает на /bitrix/modules/... — это почти наверняка агент или крон.
Шаг 2. Какие файлы и сокеты он держит
Теперь смотрим, что процесс держит открытым.
Быстрый просмотр файловых дескрипторов
ls -l /proc/$PID/fd | head
Здесь можно увидеть:
- файлы логов;
- временные файлы;
- сокеты.
Если видишь что-то вроде:
socket:[123456]
— идём дальше.
Подробно через lsof
lsof -p $PID | head -n 50
На что смотрим в первую очередь:
- соединение с MySQL;
- unix-socket
/var/lib/mysql/mysql.sock; - файлы в
/bitrix/cache,/upload,/tmp.
Важно: если процесс держит MySQL-socket — он уже внутри Битрикса и выполняет бизнес-логику, а не просто висит в PHP.
Шаг 3. На чём он реально «висит» (strace)
Если процесс живёт долго, но CPU почти не ест — он ждёт. Вопрос — чего.
Подключаемся без вмешательства
strace -p $PID -tt -T -f -s 128 -o /tmp/strace.cron_$PID.log
Оставляем на 10–20 секунд, затем Ctrl+C.
Смотрим хвост
tail -n 50 /tmp/strace.cron_$PID.log
Типовые варианты, которые я видел на практике:
futex()— ожидание блокировки (часто кеш или shared memory);read()/write()— чтение файла или сокета;poll()/select()— ожидание ответа от MySQL или Redis;open()на файле, который лежит на медленном диске.
Это ключевой момент: ты видишь не догадки, а фактические системные вызовы.

Шаг 4. htop — не просто «посмотреть нагрузку»
htop уже установлен в BitrixVM, и его часто недооценивают.
Что я делаю:
- включаю отображение Command line;
- сортирую по TIME+;
- смотрю, какие процессы живут дольше всех.
Полезные флаги:
F5— дерево процессов;F6— сортировка;F3— поиск по имени скрипта.
Очень часто проблемный агент видно сразу, без всякого strace.
Дополнительные инструменты (по ситуации)
Иногда полезно:
vmstat 1— если подозрение на I/O wait;iostat— если сервер на HDD;netstat -anp | grep $PID— если процесс держит сеть.
Ставить ничего не обязательно, но знать стоит.
Подводные камни
Из практики:
-
Агент без лимитов Бесконечный цикл + отсутствие таймаутов = вечный PHP.
-
Большие выборки ORM без
limit, особенно в CLI — классика. -
Файловый кеш Массовая работа с
/bitrix/cacheна медленном диске. -
MySQL-блокировки Процесс не «завис», он честно ждёт освобождения таблицы.
Безболезненные варианты решения
В порядке увеличения жёсткости:
- Понять, что именно делает процесс
- Дать ему дожить и исправить код
- Ограничить время выполнения (timeout, батчи)
- Переписать агент или крон
- И только потом —
kill
Слепо убивать процесс — почти всегда плохая идея.
Результат
После такого разбора у тебя есть:
- конкретный скрипт;
- конкретная точка зависания;
- понимание, это I/O, MySQL или логика;
- аргументы для фикса, а не догадки.
Практическая польза
Этот подход:
- экономит время;
- не требует перезапусков;
- применим на любом продакшене;
- даёт контроль над системой, а не иллюзию.
Если ты работаешь с BitrixVM и PHP — рано или поздно это пригодится.



Комментарии