PHP即使没有达到memory_limit也会出现内存不足错误

时间:2012-12-19 15:41:15

标签: memory php php-ini

我刚刚继承了一个带有PHP脚本的站点,该脚本一直耗尽117 MB的内存。即使我将PHP的memory_limit变量增加到312 MB也是如此,我正在通过php.ini进行此操作。

由于pcguru提供了很好的线索,现在已经解决了这个问题。请参阅下面的答案:我终于找到了答案

ini_get('memory_limit')返回php.ini中设置的值,所以我确定Apache在更改值后重新启动了。我正在使用memory_get_usage(true)来返回脚本在整个过程中各个点消耗的内存。当它达到117 MB时,它一直都会失败。

是否存在一些内部PHP限制,我不知道它是否从未为单个脚本分配超过117MB的数据?

服务器有1GB的RAM并运行CentOS。我有root shell访问权限。 PHP是版本5.3.18。 MySQL是版本5.1.66-cll。

此脚本位于用户名/密码后面,我无法提供公共访问权限。

编辑添加:

1)感谢大家的帮助。您可以在我对以下各种答案的特定用户评论的回复中找到更多信息。

2)绝对没有安装Suhosin。我检查过多个地方,包括运行脚本并检查常量并运行php -v

3)apache日志没有我收到的具体错误消息的记录。在php.ini中打开日志记录。我通过grep搜索整个日志。

4)在这种情况下是否可能报告错误的错误?

5 个答案:

答案 0 :(得分:19)

我终于找到了答案。线索来自pcguru的答案开始'因为服务器只有1 GB的RAM ......'。

在预感中,我看看Apache是​​否有自己的内存限制,因为这些可能会影响PHP分配内存的能力。在httpd.conf的顶部,我发现了这个语句:RLimitMEM 204535125

这是由whm / cpanel放在那里的。根据以下网页,whm / cpanel在虚拟服务器上错误地计算其值... http://forums.jaguarpc.com/vps-dedicated/17341-apache-memory-limit-rlimitmem.html

内存耗尽的脚本大部分都在使用,因此我将RLimitMEM增加到268435456(256 MB)并重新编写脚本。它完成了数组合并并生成了csv文件供下载。

ETA:在进一步阅读有关RLimitMEM和RLimitCPU之后,我决定将它们从httpd.conf中删除。这允许ini_set(' memory_limit',### M')工作,我现在为该特定脚本提供所需的额外内存。我还将该服务器上的RAM加倍。

感谢大家帮助我们解决这个相当棘手的问题,特别是对于那些想出解决方案的重要线索的pcguru。

答案 1 :(得分:8)

由于服务器只有1 GB的RAM,我倾向于完全耗尽系统内存。

See this thread。你得到相同的“PHP致命错误:内存不足”而不是更常见的“致命错误:允许的内存大小......”。您的错误表明系统根本无法分配更多内存,这意味着即使PHP:内部函数也无法分配更多内存,更不用说您自己的代码了。

如何将PHP配置为与Apache一起运行?作为模块还是CGI? 你可以同时运行多少个PHP进程? 你有可用的交换空间吗?

如果你在Apache中使用PHP作为模块,那么Apache有一个讨厌PHP进程分配的内存的习惯。猜测因为它无法在worker中重启PHP模块,所以只需完全重启worker。服务PHP的每个工作人员随着时间的推移只会增长到PHP内存限制,因为该工作人员提供了分配大量RAM的脚本。因此,如果您同时拥有多个工作人员,每个工作人员使用100 MB +,您将很快耗尽RAM。尝试限制Apache中的同时工作者数量。

答案 2 :(得分:2)

这可能不是您的问题的答案,但如果您从命令行运行PHP,您可以覆盖php.ini的内存限制。

php -d memory_limit=321M my_script.php

我不确定cli的默认内存限制是什么。

此外,您可以运行php --ini并检查结果。

答案 3 :(得分:2)

这不能解决为什么你的脚本在某个内存使用后死亡的原因,但你可以通过完全删除PHP脚本本身的内存限制来解决它:

ini_set('memory_limit', '-1');

这很危险。如果您有一个失控的脚本,PHP将占用内存,直到您的服务器没有剩余分配和翻倒。所以你应该只使用它,如果你确定脚本本身不是问题,并且只测试输出。

至于PHP是否对内存使用有一些每个脚本限制,没有。我亲自运行内存使用量接近1GB的脚本。

答案 4 :(得分:-6)

你的代码中有一个无限循环。