NodeJS在Mac OS上出现"EMFILE, too many open files"错误

65

有一段时间我一直遇到以下错误:

Error: EMFILE, too many open files  '/Users/blagus/Gallery/Websites/Nicsware/Pills/resources/core/auth.node.js'
    at Object.fs.openSync (fs.js:427:18)
    at Object.fs.readFileSync (fs.js:284:15)
    at Object.Module._extensions..js (module.js:473:44)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at instController  (/Users/blagus/Gallery/Websites/Nicsware/Pills/engine/mvc.node.js:79:31)
    at init (/Users/blagus/Gallery/Websites/Nicsware/Pills/engine/mvc.node.js:57:8)
    at route (/Users/blagus/Gallery/Websites/Nicsware/Pills/engine/dispatcher.node.js:268:36)

调用此文件的代码行(mvc.node.js:79)如下:

    this.currentRoute.class = require( controllerFile )[dispatchClass].bind( this );

(这是我正在创建的一个框架)

正如您所看到的,文件auth.node.js是通过REQUIRE调用的,因此使用gracefullFS和类似解决方案不适用。此外,这个问题只出现在MacOS上,而在Ubuntu上似乎工作得很好。

有什么想法吗?


auth.node.js 在做什么奇怪的事情吗? 如果我在要求 JS 文件时生成堆栈跟踪,则 fs.* 不会出现。 - robertklep
在 Linux 系统上,它表现得非常好。除此之外,只是一个简单的要求让我感到困扰。 - blagus
从堆栈跟踪来看,问题不是由require本身引起的,而是由您要求的模块引起的。但是,如果您不发布代码,那只是一个猜测... - robertklep
13个回答

57

这对我有用:

ulimit -n 10480

这里可以找到。


14
如下所述,Ryan提到默认限制为256。将其设置为10480可能过度杀伤力。逐步增加它“ulimit -n 360”。 - Lane
2
谢谢 Lane :) 有人知道如何终止进程或关闭已打开的文件吗? - Jon

48

您可以通过增加maxfiles限制来解决这个问题:

launchctl limit maxfiles 16384 16384 && ulimit -n 16384

4
我不会点踩,因为这个回答在技术上是正确的,但也非常危险,特别是自从 Lion 以来,默认的同时打开文件数量已经达到了10000个,将限制设置得太低可能会使所有正在运行的程序在一秒钟内无法使用。如果我们试图增加数量,建议将其设为16384,而不是2048。 - Igor Zinken
1
好的,这对我来说解决了问题,不再出现“错误:EMFILE,打开文件太多”!谢谢。 另外,我不确定自己在做什么,但它有效。 我很想知道这个问题背后的真正原因,为什么node会弹出这个错误消息。无论如何,还是谢谢。 - LukyVj
我同意Igor的观点;我不确定增加限制是否对某些人来说是可接受的,因为这会带来安全风险。我认为实际上,在某个时候,gulp需要“放手”文件流。一种方法是通过shell脚本链接一些gulp任务。是的,这似乎很奇怪,但在gulp中有什么替代方案呢?使用Shell或npm任务/脚本通过npm运行。 - Nick
2
你必须在开头加上sudo。直到我添加了sudo,它才起作用。 - Hamid
2
这似乎对我没有任何作用。 - ryanwebjackson
显示剩余3条评论

21

我遇到了这个错误,而ulimit和launchclt对我都没有用。

这个解决方案来自http://yabfog.com/blog/2014/10/22/yosemite-upgrade-changes-open-file-limit,对我很有效。

echo kern.maxfiles=65536 | sudo tee -a /etc/sysctl.conf
echo kern.maxfilesperproc=65536 | sudo tee -a /etc/sysctl.conf
sudo sysctl -w kern.maxfiles=65536
sudo sysctl -w kern.maxfilesperproc=65536
ulimit -n 65536 65536

然后放置

ulimit -n 65536 65536

复制到~/.bashrc


这是一个hacky的解决方案,但当您的本地机器运行不良时,它可以帮助您。 - aqm

17
我正在使用watchman。这个工具为我解决了这个错误。值得一试!!!
brew update
brew install watchman

它会监视文件和文档,并在有任何更改时触发文件处理事件。这是他们的 GitHub 仓库链接:

3
这是唯一在我机器上有效的方法,使用的系统版本为Catalina 10.15.1。 - Daniele Molinari
1
这里也是Catalina 10.15.3 - 唯一有效的解决方案。 - Imre Kelényi
4
可以提供一些背景信息,说明这个是如何工作的吗?发布两个安装命令并不是很有帮助。 - user3827326
1
嗨@Contrapak, 正如其名称所示,它只是监视文件和文档。如果有任何更改,触发文件处理事件。请查看他们的Github存储库以获得更好的理解。 https://github.com/facebook/watchman - bh4r4th

8
您的代码正在打开过多的文件。默认情况下,OS X 的最大同时打开文件数为 256。当您的代码需要一个新模块时,Node.js 需要打开文件进行读取。如果您已经达到此限制,则 Node.js 的 require 无法继续,并会抛出错误。您应该审查应用程序中调用 fs.open 的位置,并确保正确关闭所有这些文件。如果您尝试执行过多的同时文件系统读取操作,则也可能遇到此问题,因为每个待处理的读取都将是一个打开的文件。我还在使用 fs.watchFile 时遇到了这个问题,它也需要打开文件句柄。

你有没有任何资源可以确保我正在做你提到的事情?我更愿意练习更好地使用fs,而不是像其他人建议的那样不断提高限制。 - Katrina

7

检查您的ulimit。 例如,我在OSX上的初始ulimit为256。

  • 运行ulimit -n以查看限制。
  • 之后,您可以使用ulimit -n 1024设置更高的限制。

6

其他答案都对我没用。这个方法才有效:

launchctl limit maxfiles 16384 16384 

需要注意的是,这个设置不会保存在会话之间,所以除非你想为每个bash终端会话都运行它,否则建议将上面的命令放入您的~/.bashrc文件中(如果您使用zsh,则为~/.zshrc),方法如下:

vi ~/.bashrc

2

在生产环境中,您可能需要在启动时启动并在崩溃时重新启动,这意味着Mac OSX的最佳答案是为每个应用程序使用.plist文件。我使用该plist文件启动我的node应用程序(在启动时运行并在崩溃后重新启动)...在此文件中,您可以使用SoftResourcesLimit键设置每个应用程序的文件数量。

<key>KeepAlive</key>
<true/>

<key>RunAtLoad</key>
<true/>

<key>SoftResourceLimits</key>
<dict>
<key>NumberOfFiles</key>
  <integer>16384</integer>
</dict>

1

在OS X 10.10.3 Yosemite中,最大文件数已重置为256。这可能会导致npm安装出现问题。您可以使用命令ulimit -n从终端检查此限制。要将此限制更改为256以外的值,则需要创建两个配置文件。

第一个属性列表文件是/Library/LaunchDaemons/limit.maxfiles.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
    <dict>
      <key>Label</key>
        <string>limit.maxfiles</string>
      <key>ProgramArguments</key>
        <array>
          <string>launchctl</string>
          <string>limit</string>
          <string>maxfiles</string>
          <string>65536</string>
          <string>65536</string>
        </array>
      <key>RunAtLoad</key>
        <true/>
      <key>ServiceIPC</key>
        <false/>
    </dict>
  </plist>

第二个属性列表文件 /Library/LaunchDaemons/limit.maxproc.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple/DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  <plist version="1.0">
    <dict>
      <key>Label</key>
        <string>limit.maxproc</string>
      <key>ProgramArguments</key>
        <array>
          <string>launchctl</string>
          <string>limit</string>
          <string>maxproc</string>
          <string>2048</string>
          <string>2048</string>
        </array>
      <key>RunAtLoad</key>
        <true />
      <key>ServiceIPC</key>
        <false />
    </dict>
  </plist>

设置正确的所有权和权限:

sudo chown root:wheel /Library/LaunchDaemons/limit.maxfiles.plist
sudo chown root:wheel /Library/LaunchDaemons/limit.maxproc.plist
sudo chmod 644 /Library/LaunchDaemons/limit.maxfiles.plist
sudo chmod 644 /Library/LaunchDaemons/limit.maxproc.plist

将所需的限制设置到bash配置文件(.bashrc.bashprofile或类似文件)中:

ulimit -n 65536
ulimit -u 2048

确保bash配置文件的权限相同:

chmod 644 .your_bash_profile_file

重新启动电脑并检查 ulimit -n 最大文件数。它应该是 65536,您应该能够将其更改为任何低于此值的数字。

来源:http://docs.basho.com/riak/latest/ops/tuning/open-files-limit/#Mac-OS-X


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接