Назад | Перейти на главную страницу

Невозможно снять ограничение на использование памяти для PHP-скрипта

Ситуация

У меня проблема с тем, что PHP-скрипт получает следующее сообщение об ошибке:

Fatal error: Out of memory (allocated 359923712) (tried to allocate 72 bytes) in /path/to/piwik/core/DataTable.php on line 969

Я запускаю сценарий: /path/to/piwik/misc/cron/archive.sh

Я предполагаю, что это байты, что означает, что общий объем составляет примерно 360 МБ.

Во всех смыслах и целях я увеличил лимит памяти на сервере намного выше 360 МБ, но это число (плюс-минус байт), на котором постоянно возникают ошибки.

пожалуйста, обратите внимание: Этот вопрос не ни об устранении утечки памяти в скрипте, ни о том, почему сам скрипт использует так много памяти. Скрипт является частью процесса архивирования Piwik, поэтому я не могу просто исправить какие-либо утечки памяти и т. Д. Подробнее об этом скрипте и почему я увеличиваю лимит памяти см. «Как настроить автоархивирование»

Вопрос

Учитывая, что сценарий пытается использовать более 360 МБ памяти, которую я не могу изменить, почему мне не представляется возможным увеличить объем памяти, доступной для php на моем сервере?

Обновление 23 июня: См. «Что я пробовал»> «Увеличение пределов памяти для каждого процесса Linux» ниже для справки ... Если я установил ulimit -v 1024000, затем проверьте это с помощью ulimit -v Я получаю правильное значение «1024000». Если я снова запущу сценарий, он пойдет намного дальше, но в конечном итоге выйдет ошибка с тем же пределом памяти (~ 360 МБ). Если я сразу проверю ulimit -v, оно сброшено до исходного значения "524288". Похоже, это может быть основной причиной проблемы.


Что я пробовал

Увеличение memory_limit PHP

Учитывая файл php.ini:

php -i | grep php.ini
Configuration File (php.ini) Path => /usr/local/lib
Loaded Configuration File => /usr/local/lib/php.ini

Я редактировал этот файл, поэтому директива memory_limit читает;

memory_limit = -1

Перезапустите Apache и убедитесь, что новое значение застряло;

$ php -i | grep memory_limit
memory_limit => -1 => -1

Запустите скрипт и получите ту же ошибку.

Я также пробовал 1G, 768Mи т. д., все к одному результату (т. е. без изменений).

Обновление 22 июня: На основе Помощь Вангела, Я попытался установить post_max_size до 20M в сочетании с настройкой memory_limit. Опять же, это не действует.

Обновление 23 июня: На основе помощь олефевра, Я могу подтвердить, что пользователь, запускающий скрипт, имеет разрешение на чтение / запись в файл php.ini, содержащий настройки memory_limit.

Снятие ограничения памяти для дочерних процессов Apache

Я нашел и отредактировал файл httpd.conf, чтобы убедиться, что нет RLimitMEM директива.

Затем я использовал WHM Apache Configuration> Memory Usage Restrictions, чтобы сгенерировать ограничение, которое было заявлено на уровне 1000M (и подтверждено проверкой httpd.conf).

Оба они не привели к изменению скрипта с ошибкой на уровне 360 МБ.

Увеличение пределов памяти для каждого процесса в Linux

Текущие ограничения, установленные в системе:

$ ulimit -m
524288

$ ulimit -v
524288

Я попытался установить неограниченное значение для обоих:

$ ulimit -m unlimited
$ ulimit -v unlimited

$ ulimit -m
unlimited

$ ulimit -v
unlimited

Опять же, это не привело к улучшению моей проблемы.

Обновление 23 июня: Я столкнулся с подобной проблемой здесь. Если я установлю ulimit -v 1024000, затем проверьте это с помощью ulimit -v Я получаю правильное значение «1024000». Если я снова запущу сценарий, он пойдет намного дальше, но в конечном итоге выйдет ошибка с тем же пределом памяти. Если я сразу проверю ulimit -v, оно сброшено до исходного значения "524288". Похоже, это может быть основной причиной проблемы.


Моя установка

$ cat /etc/redhat-release
CentOS release 5.5 (Final)

$ uname -a
Linux example.com 2.6.18-164.15.1.el5 #1 SMP Wed Mar 17 11:30:06 EDT 2010 x86_64 x86_64 x86_64 GNU/Linux

$ php -i | grep "PHP Version"
PHP Version => 5.2.9

$ httpd -V
Server version: Apache/2.0.63
Server built:   Feb  2 2011 01:25:12
Cpanel::Easy::Apache v3.2.0 rev5291
Server's Module Magic Number: 20020903:13
Server loaded:  APR 0.9.17, APR-UTIL 0.9.15
Compiled using: APR 0.9.17, APR-UTIL 0.9.15
Architecture:   64-bit
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/prefork"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D HTTPD_ROOT="/usr/local/apache"
 -D SUEXEC_BIN="/usr/local/apache/bin/suexec"
 -D DEFAULT_PIDLOG="logs/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_LOCKFILE="logs/accept.lock"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"

Выход $ php -i: http://pastebin.com/EiRut6Nm

М. Тиббитс ответ намекает на то, что Piwik может использовать больше ресурсов в процессе архивирования.

Существует ограничение на размер выполняемой команды SQL, которое по умолчанию составляет всего 1 МБ. Для получения дополнительной информации; Пакет слишком большой

Чтобы увеличить ограничение размера в MySQL, отредактируйте /etc/my.cnf и установить max_allowed_packet=32M

Убедитесь, что лимит памяти PHP установлен достаточно высоким для разветвленного процесса, отредактировав /usr/local/lib/php.ini и установить memory_limit = 512M

Наконец, убедитесь, что все процессы имеют жесткое ограничение не менее 1 ГБ, прежде чем система отключит их, выполнив ulimit -v 1048576 в командной строке.

Обновить

ulimit -v 1048576 только поднимет мягкий предел. Если жесткий лимит недостаточно высок, система автоматически сбросит мягкое ограничение на жесткое.

Чтобы установить жесткое ограничение, добавьте -H переключатель:

ulimit -vH 1048576

с последующим увеличением мягкого лимита до этого значения:

ulimit -vS 1048576

Задний план:

Я только что взял текущую версию Piwik - в версии 1.5 строка 969 выглядит так:

public function addRowsFromSerializedArray( $stringSerialized )
{
    $serialized = unserialize($stringSerialized);
    if($serialized === false)
    {
        throw new Exception("The unserialization has failed!");
    }
    $this->addRowsFromArray($serialized);
}

и конкретно $serialized = unserialize($stringSerialized);. Призыв к unserialize может быть невероятно интенсивным по памяти. Есть отличный пост Вот.

Как вы отметили, это явно не ошибка в вашем скрипте и действительный Out of Memory.

Предложение: В файле конфигурации, как указано выше в моем комментарии:

/.../piwik/config/global.ini.php

Я думаю, вам может потребоваться увеличить один из этих лимитов:

# during archiving, Piwik will limit the number of results recorded, for performance reasons
# maximum number of rows for any of the Referers tables (keywords, search engines, campaigns, etc.)
# this limit will also be applied to the Custom Variables names and values reports
datatable_archiving_maximum_rows_referers = 1000
# maximum number of rows for any of the Referers subtable (search engines by keyword, keyword by campaign, etc.)
datatable_archiving_maximum_rows_subtable_referers = 50

# maximum number of rows for any of the Actions tables (pages, downloads, outlinks)
datatable_archiving_maximum_rows_actions = 500
# maximum number of rows for pages in categories (sub pages, when clicking on the + for a page category)
# note: should not exceed the display limit in Piwik_Actions_Controller::ACTIONS_REPORT_ROWS_DISPLAY
#       because each subdirectory doesn't have paging at the bottom, so all data should be displayed if possible.
datatable_archiving_maximum_rows_subtable_actions = 100

# maximum number of rows for other tables (Providers, User settings configurations)
datatable_archiving_maximum_rows_standard = 500

где я заменил точки с запятой на знаки #, чтобы сделать автоцвет sf читабельным.

Вы также можете попробовать добавить:

CMD_TO_CHECK_SETTINGS="$PHP_BIN -i > /tmp/piwik-php-env.out"
$CMD_TO_CHECK_SETTINGS

в archive.sh, чтобы определить, есть ли другие настройки, которые отменяют файл php.ini.

это определенно ошибка скрипта. Кажется, что есть утечка памяти, поэтому независимо от того, насколько вы увеличиваете лимит памяти в PHP, он его достигнет.

Я использую Piwik на базовом уровне и не помню, чтобы когда-либо использовал скрипт архивирования напрямую. Piwik все еще немного глючит, но последняя версия - 1.4, и кажется, что в ней гораздо меньше ошибок, чем в предыдущих.

Я рекомендую не возиться с настройками системы или PHP ради исправления ошибочного скрипта. Посещение форума поддержки piwik может быть лучшей идеей

Вы пробовали использовать опцию командной строки define? php -d memory_limit = 512M test.php

Кстати, вы проверили, что php.ini читается пользователем, запускающим php из командной строки?

Лимит Linux на процесс / пользователя не имеет к этому никакого отношения; ошибка, которую вы получаете, конкретно связана с PHP.

В связи с этим, я подозреваю, что где-то есть директива ini_set, которая заменяет ваш лимит; даже если вы поместите ini_set в файл верхнего уровня, файл нижнего уровня перезапишет его.

Просто запустите `grep -r -i" ini_set "/ path / to / piwiki" и посмотрите, не перезаписывают ли они ограничение вручную.

Можете ли вы подтвердить, в каком конфигурационном файле вы изменили ограничения памяти? Обратите внимание, что есть две разные конфигурации: одна для PHP, выполняемая через веб-сервер, а вторая для PHP, выполняемая через CLI.

~$ ls /etc/php5/
apache2  cli  conf.d
~$ ls /etc/php5/apache2/
conf.d  php.ini
~$ ls /etc/php5/cli/    
conf.d  php.ini

Кроме того, если это выполняется через браузер, в том же каталоге, где находится фактический скрипт, создайте файл temp.php со следующим содержимым:

<?php phpinfo(); ?>

Проверьте, что memory_limit отображается при переходе к этому файлу.

У меня была эта проблема на прошлой неделе, мое решение в CentOS rehel -

nano /etc/httpd/conf/hpptd.conf

search RLimitMEM директива delete или comented не использует эти директивы или, если используется, разрешает значение 2000000

  • сохраните этот файл
  • перезапустить службу
  • перезапуск службы httpd