Nodejs readdir时抛出异常:EMFILE, too many open files

Nodejs readdir时抛出异常:EMFILE, too many open files

自己google了很多,比如ulimit -n 65535、引入graceful-fs、引入filequeue 但是还是没有解决 有人遇到过同类问题吗?怎么解决的?

5 回复

Node.js readdir 时抛出异常:EMFILE, too many open files

在使用 Node.js 进行文件系统操作时,有时会遇到 EMFILE: Too many open files 的错误。这种错误通常发生在频繁地打开和关闭文件或目录时,超过了操作系统允许的最大文件描述符数量。

解决方案

  1. 调整系统限制: 你可以通过修改系统的文件描述符限制来解决这个问题。在 Linux 系统上,可以通过以下命令临时增加限制:

    ulimit -n 65535
    

    如果需要永久更改,可以编辑 /etc/security/limits.conf 文件,添加或修改以下行:

    * soft nofile 65535
    * hard nofile 65535
    
  2. 使用 graceful-fsgraceful-fs 是一个对 fs 模块进行封装的库,可以更优雅地处理文件操作中的异常情况。你可以通过 npm 安装它,并用它替换标准的 fs 模块:

    npm install graceful-fs
    

    使用示例:

    const fs = require('graceful-fs');
    
    fs.readdir('/path/to/directory', (err, files) => {
      if (err) {
        console.error('Error reading directory:', err);
        return;
      }
      console.log('Files:', files);
    });
    
  3. 使用 filequeuefilequeue 可以帮助你管理文件操作队列,避免同时打开过多的文件。你可以通过 npm 安装它:

    npm install filequeue
    

    使用示例:

    const FileQueue = require('filequeue');
    const queue = new FileQueue();
    
    queue.push((cb) => {
      fs.readdir('/path/to/directory', cb);
    }, (err, files) => {
      if (err) {
        console.error('Error reading directory:', err);
        return;
      }
      console.log('Files:', files);
    });
    
  4. 优化代码逻辑: 确保你在处理文件时正确地关闭了文件句柄。例如,在读取大量小文件时,可以尝试批量处理文件,而不是一次性打开所有文件。

通过以上方法,你应该能够解决 EMFILE 错误,并确保你的 Node.js 应用程序能够高效地处理文件系统操作。


一般就是ulimit的問題吧 樓主什麼系統?OSX的話ulimit -n 65535是不行的吧

centos系统 可能是因为项目中有.git文件,里面的文件太多了

看一下文件描述符用了多少 一般是達到上線沒法申請更多的才會報這個錯 如果是這種情況還是比較好解決的 查查哪個進程用掉了這麼多再查就好了

当你在使用 Node.js 的 readdir 函数遍历大量文件或目录时,可能会遇到 “EMFILE, too many open files” 异常。这个问题通常是由于操作系统对文件描述符的数量限制导致的。你可以通过调整系统级别的文件描述符限制来解决这个问题。

解决方案

  1. 修改系统级别的文件描述符限制

    在 Linux 系统中,可以通过修改 /etc/security/limits.conf 文件来增加每个用户的文件描述符限制:

    * soft nofile 65535
    * hard nofile 65535
    

    然后需要重启系统或者重新登录以使更改生效。

  2. 使用 fs.promisesasync/await

    使用 fs.promises.readdirasync/await 可以更好地管理文件描述符的使用。这样可以确保在每次操作后及时关闭文件描述符。

    const fs = require('fs').promises;
    
    async function readDir(path) {
      try {
        const files = await fs.readdir(path);
        console.log(files);
      } catch (err) {
        console.error(err);
      }
    }
    
    readDir('/path/to/directory');
    
  3. 使用 graceful-fs

    graceful-fs 是一个被广泛使用的库,它会在底层自动处理文件描述符的限制。

    npm install graceful-fs
    

    然后在你的代码中使用 graceful-fs 替换 fs 模块:

    const fs = require('graceful-fs');
    
    fs.readdir('/path/to/directory', (err, files) => {
      if (err) {
        console.error(err);
      } else {
        console.log(files);
      }
    });
    
  4. 限制并发读取数量

    如果你需要遍历大量的文件或目录,可以考虑使用队列来限制同时打开的文件描述符数量。

    const fs = require('fs').promises;
    const path = require('path');
    
    async function processFiles(dirPath) {
      const files = await fs.readdir(dirPath);
      const queue = [];
    
      for (const file of files) {
        const filePath = path.join(dirPath, file);
        queue.push(filePath);
    
        // 控制并发数量
        if (queue.length > 100) {
          await processQueue(queue);
          queue.length = 0;
        }
      }
    
      if (queue.length) {
        await processQueue(queue);
      }
    }
    
    async function processQueue(queue) {
      for (const filePath of queue) {
        try {
          const stats = await fs.stat(filePath);
          if (stats.isDirectory()) {
            await processFiles(filePath);
          }
        } catch (err) {
          console.error(err);
        }
      }
    }
    
    processFiles('/path/to/directory');
    

这些方法可以帮助你解决 “EMFILE, too many open files” 异常。希望这些建议对你有所帮助!

回到顶部