无法删除 PHP 脚本的内存使用限制

无法删除 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

我假设这些数字是字节,这意味着总数约为 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

运行脚本,出现同样的错误。

我也尝试过1G768M等等,结果都一样(即没有变化)。

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 -ihttp://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

ulimit -v 1048576最后,通过命令行执行,确保所有进程在系统关闭之前至少有 1G 的硬限制。

更新

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”并查看他们是否手动覆盖限制。

相关内容