PHP警告:exec()无法派生


PHP Warning: exec() unable to fork

所以这里有一些关于我的设置的背景信息。使用apache和php 5.2.17运行Centos。我有一个网站,列出了许多不同零售商网站的产品。我有爬行器脚本,运行以从每个网站抓取产品。由于每个网站都是不同的,所以必须自定义每个爬网程序脚本来爬网特定的零售商网站。所以基本上我每个零售商有一个爬虫。此时,我有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个爬网程序以来,我最近才开始看到这种情况的发生。它并不总是同一个爬网程序得到这个错误——它将是其中任何一个在随机时间无法派生其restart exec命令的爬网程序。

有人知道是什么原因导致php无法分叉,或者可能有更好的方法来处理这些过程,从而一起绕过错误吗?是否存在我应该研究的过程限制或类似的性质?提前感谢您的帮助!

过程限制

";是否存在我应该研究的过程限制

怀疑有人(系统管理员?)设置了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";
}

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

问题通常是由系统或进程或可用内存不足引起的。通过运行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内存,看看它是否降到几百以内。如果是这样,您将需要找到一种方法来运行您的程序,同时消耗较少的内存。

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

ulimit -n 4096

对于其他遇到此问题的人来说,这可能是本问题答案中列出的几个问题。

然而,我的问题是我的nginx用户没有一个合适的shell来执行我想要的命令。将.bashrc添加到nginx用户的主目录中解决了这个问题。