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 >/dev/null &]
这应该是重新启动这个特定爬虫的原因,但是由于它“无法分叉”,它从未重新启动,并且爬虫的原始实例像往常一样结束。
显然这不是权限问题,因为这 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() 无法分叉的主要内容,如果未能解决你的问题,请参考以下文章