На моем сервере работает Ubuntu 12.04 LTS (точно), и у меня странная проблема. На сервере размещен большой веб-сайт, который используется для сбора данных. Веб-сайт написан на PHP и использует Zend Framework. Данные находятся в базе данных MySQL. Часть этих данных (из опросов) преобразуется в файлы Excel (с использованием библиотеки PHPExcel) каждый час (задание cron). Этот процесс (сценарий PHP / Zend Framework) выполняется для каждого клиента, каждый с другим набором данных, и иногда может занять много времени (30+ минут).
Как только он достигает 30-минутной отметки, состояние процесса меняется с R на D. Что странно, так это то, что процессы в состоянии D обычно «неубиваемы», но этот процесс можно убить, как и любой другой процесс. Вот пример вывода, когда процесс работает нормально:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
www 16089 0.5 0.8 311640 31708 ? S 09:34 0:39 /usr/sbin/apache2 -k start
www 17635 0.6 0.6 305020 23396 ? S 10:52 0:18 /usr/sbin/apache2 -k start
www 18520 0.0 0.0 63104 1960 pts/0 S 11:32 0:00 su www
www 18521 0.0 0.1 23236 4516 pts/0 S 11:32 0:00 bash
www 18621 98.8 68.1 2665208 2416568 pts/0 R 11:33 10:48 php run.php -a hourly
www 18659 0.6 0.6 302848 22948 ? S 11:34 0:03 /usr/sbin/apache2 -k start
www 18876 0.0 0.0 18160 1244 pts/0 R+ 11:44 0:00 ps ux
Как видите, этот процесс требует больших ресурсов: он уже сильно обрезан и все еще подвергается операции, но мне нужно его завершить, чтобы я мог получить итоговые файлы Excel. Процесс регистрирует множество своих действий (~ 300 КБ журнала для каждого файла Excel), и файлы журнала всегда заканчиваются внезапно. Я нигде не регистрировал ошибок.
Вот тот же список процессов сразу после 30-минутной отметки:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
www 18034 1.0 0.7 312412 26632 ? S 11:13 0:33 /usr/sbin/apache2 -k start
www 18245 2.1 0.4 303656 16912 ? S 11:25 0:49 /usr/sbin/apache2 -k start
www 18520 0.0 0.0 63104 296 pts/0 S 11:32 0:00 su www
www 18521 0.0 0.0 23236 968 pts/0 S 11:32 0:00 bash
www 18621 96.3 85.0 3969192 3012596 pts/0 D 11:33 30:08 php run.php -a hourly
www 18659 0.4 0.5 302856 19136 ? S 11:34 0:08 /usr/sbin/apache2 -k start
www 19431 0.0 0.0 18160 1240 pts/0 R+ 12:04 0:00 ps ux
Если оставить процесс запущенным, он все равно потребляет ресурсы, но ничего не делает. Больше ничего не регистрируется.
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
www 18621 9.1 80.0 4030532 2835032 ? D 11:33 33:19 php run.php -a hourly
Обратите внимание, что состояние процесса меняется ровно через 30 минут, он будет обрабатывать больше или меньше данных в зависимости от загрузки сервера. Что интересно, это происходит только на рабочем сервере. На моем сервере разработки, Ubuntu 12.04, этой проблемы нет.
Есть ли что-нибудь, что могло бы заставить процессы нормально работать максимум 30 минут, а затем изменить свое состояние на D? Что может привести к тому, что PHP-скрипт окажется в состоянии D?
Во-первых, процесс в состоянии D находится в непрерывный сон (обычно IO).
Обычно то, что вызывает перевод процесса в это состояние, - это выполнение блокировка системного вызова.
Вы можете увидеть, какой последний вызов ваш процесс сделал, используя strace
:
strace -fp <pid>
Поскольку состояние D обычно вызывается операцией ввода-вывода, также полезно проверить, какие файлы открыл процесс, используя lsof
:
lsof -p <pid>