У меня проблема с тем, что 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