Сегодня обнаружил пренеприятную вещь. Если в WP, будучи авторизованным, производить какие-либо действия, через некоторое время сайт перестаёт отзываться и выпадает в осадок на непродолжительное время. После этого всё опять начинает работать, как ни в чём не бывало, до следующего такого же события. Я полез в логи в поисках источника проблемы. В /var/log/syslog
я нашел исчерпывающую информацию:
Dec 22 20:39:41 < хост убран > suhosin[19857]: ALERT - script tried to increase memory_limit to 268435456 bytes which is above the allowed value (attacker '< ip убран >', file 'wp-admin/admin.php', line 109)
Оказалось, что это полезняшка-Suhosin прибивает скрипт wp-admin/admin.php
по причине того, что последний по непонятной причине начинает жрать очень уж много памяти. Гораздо больше, чем задано в настройках PHP. Начав копаться в движке, я обнаружил, что разработчики весьма щедро одарили свой движок памятью (wp-includes/default-constants.php:27
):
if ( ! defined( 'WP_MAX_MEMORY_LIMIT' ) ) {
define( 'WP_MAX_MEMORY_LIMIT', '256M' );
}
Подобная запись присутствовала в WP и раньше. Тогда значение просто было жёстко прописано в те же 256Мб. В конфиге php у меня установлено максимальное значение в 128Мб. Именно по этой причине Suhosin и валил выполняющийся скрипт.
На данный момент я не очень представляю, чего же такого делает admin.php, что требует больше 128 мегабайт памяти. Особенно учитывая, что это происходит во время отправки комментария. Не смотря на то, что скрипту требуется память, я решил не раздвигать установленные в 128Мб рамки. Скорее наоборот, я решил придавить Wordpress этими 128 мегабайтами. Как видно из кода выше, это совсем нетрудно сделать — достаточно определить константу WP_MAX_MEMORY_LIMIT
в wp-config.php
:
define( 'WP_MAX_MEMORY_LIMIT', '128M' );
Тогда вышеупомянутый код в wp-includes/default-constants.php
не будет выполняться. Конечно, это полурешение. Более того, я ожидаю, что, если скрипту понадобится больше 128Мб, он также будет убиваться, но уже интерпретатором PHP. Однако, я все же посмотрю, как оно будет работать.
а как установить какой конкретно скрипт жрет память?
Можно определить по записям в логах, как например, в первой вставке кода в этой статье. Если же ты имеешь в виду определение скрипта, который был подключен в том, который описан в логах, то тут вариантов всего ничего. Первый - поставить что-нибудь типа xdebug, тогда в логах, выводе в консоль и/или (в зависимости от настроек) в выводе в браузер появятся уведомления о вызовах функций в несколько уровней вложенности. Благодаря этому можно отследить, какой же именно скрипт виноват. Однако, я настоятельно рекомендую не ставить xdebug на продакшн-сервере, т.к. это приведет к открытию важной информации, совершенно не нужной посетителям, и возможно поломает разметку страницы. В такой ситуации, когда все-таки нужно отследить утечки памяти и прочие глюки с xdebug, лучше сделать это на тестовом сервере. Пусть даже у себя на рабочем компьютере. Можно более интенсивно использовать xdebug - при ручном дебаггинге кода, когда вносятся изменения в собственно код для получения данных от профилировщика xdebug, после исследования которых можно получить много хорошей информации об узких местах в скрипте. А второй вариант - руками, посредством ряда экспериментов. Такой вариант долог, менее удобен в виду того, что придется вручную прочесывать чуть ли не весь код, который непосредственно либо опосредованно инклюдится в этот файл.