【问题标题】:PHP Warning: exec() unable to forkPHP 警告:exec() 无法分叉
【发布时间】: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 无法分叉,或者甚至是更好的方法来处理这些进程以一起解决错误?是否有我应该研究的过程限制或类似的东西?提前感谢您的帮助!

【问题讨论】:

    标签: php centos


    【解决方案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()。请参考stackoverflow.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 内存,看看它是否落入数百个低位。如果是这样,您将需要找到一种方法来运行您的程序,同时消耗更少的内存。

      【讨论】:

        猜你喜欢
        • 2012-01-18
        • 1970-01-01
        • 2015-01-27
        • 2023-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-04
        • 1970-01-01
        相关资源
        最近更新 更多