现状
我在使用 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
我假设这些数字是字节,这意味着总数约为 360MB。
无论出于什么目的和意图,我都已将服务器的内存限制增加到远高于 360MB,但这个数字(加减一个字节)始终会导致错误。
请注意:这个问题是不是关于修复脚本中的内存泄漏,以及脚本本身为何使用如此多内存的原因。该脚本是 Piwik 归档过程的一部分,因此我无法修复任何内存泄漏等。有关此脚本的更多信息以及我增加内存限制的原因,请参阅“如何设置自动存档”
问题
鉴于脚本试图使用超过 360MB 的内存,而我无法更改这一点,为什么我似乎无法增加服务器上可用的 php 内存量?
6 月 23 日更新:请参阅下面的“我尝试过的方法”>“增加 Linux 的每个进程内存限制”了解背景信息...如果我设置了ulimit -v 1024000
,然后用它检查,ulimit -v
我会得到正确的值“1024000”。如果我再次运行该脚本,它会进一步进展,但最终会出错,因为已经达到了相同的内存限制(~360MB)。如果我立即检查ulimit -v
,它已重置为原始值“524288”。这似乎可能是问题的根本原因。
我尝试过的方法
增加 PHP 的 memory_limit
给定 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
等等,结果都一样(即没有变化)。
6 月 22 日更新: 基于Vangel 的帮助,我尝试将 设置post_max_size
为 20M 并结合设置memory_limit
。同样,这没有效果。
6 月 23 日更新: 基于olefebvre 的帮助,我可以确认运行脚本的用户对包含设置的 php.ini 文件具有读/写权限memory_limit
。
删除 Apache 子进程的内存限制
我已经找到并编辑了 httpd.conf 文件以确保没有RLimitMEM
指令。
然后我使用 WHM 的 Apache 配置 > 内存使用限制来生成一个限制,它声称限制为 1000M(并通过检查 httpd.conf 进行确认)。
这两者都不会导致 360MB 时的脚本错误发生变化。
增加 Linux 每个进程的内存限制
系统当前设置的限制:
$ ulimit -m
524288
$ ulimit -v
524288
我试图将这两项都设置为无限制:
$ ulimit -m unlimited
$ ulimit -v unlimited
$ ulimit -m
unlimited
$ ulimit -v
unlimited
再一次,这并没有改善我的问题。
6 月 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
答案1
背景:
我刚刚获取了 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
可能会占用大量内存。有一篇很好的文章这里。
正如你所注意到的,这显然不是你脚本中的错误,而是一个有效的内存不足。
建议:在配置文件中,如我上面的评论所述:
/.../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 文件。
答案2
M. Tibbits 回答暗示允许 Piwik 在存档过程中使用更多资源。
SQL 命令的执行大小是有限制的,默认仅为 1MB。更多信息;数据包太大
要增加 MySQL 中的大小限制,请编辑/etc/my.cnf
并设置max_allowed_packet=32M
/usr/local/lib/php.ini
通过编辑和设置确保每个分叉进程的 PHP 内存限制设置得足够高memory_limit = 512M
最后,通过命令行执行,确保所有进程在系统关闭之前至少有 1G 的硬限制。ulimit -v 1048576
更新
ulimit -v 1048576
只会提高柔软的限制。如果难的限制不够高,系统将自动将软限制重置为硬限制。
要设置硬限制,请添加开关-H
:
ulimit -vH 1048576
然后将软限制增加到此值:
ulimit -vS 1048576
答案3
这肯定是脚本错误。似乎存在内存泄漏,因此无论你将 PHP 中的内存限制增加多少,它都会达到该限制。
我只是在基础层面上使用 Piwik,不记得曾经直接使用过存档脚本。Piwik 仍然有点问题,但最新版本是 1.4,似乎比以前的版本问题少得多。
我建议不要为了容纳错误的脚本而乱改系统或 PHP 设置。访问 piwik 支持论坛可能是一个更好的主意
答案4
Linux 每个进程/用户的限制与此无关;您收到的错误与 PHP 特别相关。
在这一点上,我怀疑某处有 ini_set 指令会覆盖你的限制;即使你将 ini_set 放在顶层文件中,较低级别的文件也会覆盖它。
只需运行“grep -r -i“ini_set”/path/to/piwiki”并查看他们是否手动覆盖限制。