PHP 警告:exec() 无法分叉

Posted

技术标签:

【中文标题】PHP 警告:exec() 无法分叉【英文标题】:PHP Warning: exec() unable to fork 【发布时间】:2014-01-06 02:07:28 【问题描述】:

所以这里有一些关于我的设置的背景信息。使用 apache 和 php 5.2.17 运行 Centos。我有一个网站,列出了许多不同零售商网站的产品。我有爬虫脚本运行以从每个网站抓取产品。由于每个网站都不同,因此必须自定义每个爬虫脚本以爬取特定的零售商网站。所以基本上我每个零售商都有 1 个爬虫。此时我有 21 个爬虫,它们不断运行以收集和刷新这些网站的产品。每个爬虫都是一个 php 文件,一旦 php 脚本运行完毕,它会检查以确保它自己的唯一实例正在运行,并且在脚本的最后它使用 exec 重新启动自己,同时原始实例关闭。这有助于防止内存泄漏,因为每个爬虫在关闭之前都会自行重启。但是最近我会检查爬虫脚本并注意到其中一个不再运行,并且在错误日志中我发现以下内容。

PHP Warning:  exec() [<a href='function.exec'>function.exec</a>]: Unable to fork [nice -n 20 php -q /home/blahblah/crawler_script.php &gt;/dev/null &amp;]

这应该是重新启动这个特定爬虫的原因,但是由于它“无法分叉”,它从未重新启动,并且爬虫的原始实例像往常一样结束。

显然这不是权限问题,因为这 21 个爬虫脚本中的每一个在其运行结束时每 5 或 10 分钟运行一次此 exec 命令,并且大部分时间它都按应有的方式运行。这似乎每天发生一次或两次。似乎这是某种限制,因为自从我添加了第 21 个爬虫后,我才刚刚开始看到这种情况发生。而且它并不总是同一个爬虫得到这个错误,它会是随机时间中的任何一个无法分叉其重新启动执行命令的爬虫。

有没有人知道是什么导致 php 无法分叉,或者甚至是更好的方法来处理这些进程以一起解决错误?是否有我应该研究的过程限制或类似的东西?提前感谢您的帮助!

【问题讨论】:

【参考方案1】:

进程限制

“是否有我应该研究的进程限制”

怀疑有人(系统管理员?)设置了max user process的限制。你能试试这个吗?

$ ulimit -a
....
....
max user processes              (-u) 16384
....

在 PHP 中运行前面的命令。类似的东西:

echo system("ulimit -a");

我搜索了php.ini或httpd.conf是否有这个限制,但没有找到。

错误处理

“甚至更好的方法来处理这些过程以一起解决错误?

exec()的第三个参数返回$cmd的退出码。 0 表示成功,非零表示错误代码。参考http://php.net/function.exec。

exec($cmd, &$output, &$ret_val);

if ($ret_val != 0)

    // do stuff here

else

    echo "success\n";

【讨论】:

ulimit -a 在 php 中运行时返回最大用户进程 (-u) 257294 从 ssh (root) 运行时我得到 14335。我喜欢最后的脚本来测试 shell 命令是否失败了,我可以在循环中使用它来重试,直到它通过为止。 @DaneLandanHarvey 你好,Dane。是的,我认为你需要跟踪exec() 的返回码,并根据错误码确定你应该做什么。谢谢。 我现在已经将 exec 的返回码实现到一个 while 循环中,所以它现在会休眠 2 秒并重试直到成功。这会起作用,但 Ide 仍然想知道最初是什么导致了问题。感谢您的帮助 InoS Heo! 这是我得到的:警告:出于安全原因,system() 已被禁用 @Binod 如果您没有修改 php.ini 的权限,则无法打开 system()。请参考***.com/questions/13121185/…【参考方案2】:

对于遇到此问题的任何其他人,可能是此问题的答案中概述的几个问题。

但是,我的问题是我的 nginx 用户没有合适的 shell 来执行我想要的命令。将 .bashrc 添加到 nginx 用户的主目录可以解决此问题。

【讨论】:

【参考方案3】:

在我的情况下(大型 PHPUnit 测试套件),一旦进程达到 57% 的内存使用率,它就会说 unable to fork。所以,还有一点需要注意,它可能不是进程限制,而是内存。

【讨论】:

为什么是 57% 而不是 100%? 57% 有什么特别之处? 如果所有其他进程使用的内存百分比恒定,则 Derek 的 PHP 内存限制n 可能等于使用的总内存的 57%(与其他进程相结合)。这可能就是他提到它的原因。【参考方案4】:

我遇到了同样的问题,我尝试了这个,它对我有用;

ulimit -n 4096

【讨论】:

只是向阅读答案的人澄清。此命令将 open files 限制更改为 4096 @Nikita웃 很重要,因为-n ...但是-u我们正在谈论max user processes 为什么是 4096?有什么特别的吗?【参考方案5】:

问题通常是由系统或进程或可用内存不足引起的。通过运行free -m 确保您有足够的资源。您将得到如下结果:

total used free shared buffers cached Mem: 7985 7722 262 19 189 803 -/+ buffers/cache: 6729 1255 Swap: 0 0 0

缓冲区/缓存行是您要查看的内容。请注意,这台机器上的可用内存为 1255 MB。运行您的程序时,请继续尝试free -m 并检查free 内存,看看它是否落入数百个低位。如果是这样,您将需要找到一种方法来运行您的程序,同时消耗更少的内存。

【讨论】:

以上是关于PHP 警告:exec() 无法分叉的主要内容,如果未能解决你的问题,请参考以下文章

管道、分叉和​​非阻塞 IPC

如何在分叉进程中处理套接字连接

PHP 使用PHP分叉进程

检查一个分叉的孩子是不是已经在 perl 中执行

分叉后libev中的分段错误

Maven:如何在分叉的 JVM 中执行依赖项?