Node.jsで「EMFILE: too many open files」になる場合の原因と対処方法

Node.jsで「EMFILE: too many open files」エラー

Next.jsのビルド時に、下記エラーが発生しビルド中断が発生

環境:Amazon Linux 2

Node.js version 16.13.0

glob error [Error: EMFILE: too many open files, scandir '/home/ec2-user/xxx'] {
  errno: -24,
  code: 'EMFILE',
  syscall: 'scandir',
  path: '/home/ec2-user/xxx'
}
info  - Creating an optimized production build .node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);
          ^

[Error: EMFILE: too many open files, scandir '/home/ec2-user/xxx'] {
  errno: -24,
  code: 'EMFILE',
  syscall: 'scandir',
  path: '/home/ec2-user/xxx'
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

ファイルディスクリプタの上限設定が原因

Linux OSに設定されているファイルディスクリプタの設定値が原因の模様

ファイルディスクリプタとは、プログラムからファイルを操作する際、操作対象のファイルを識別・同定するために割り当てられる番号。OSにアクセスを依頼する際にファイルを指定するのに用いられる整数値である。主にUNIX系OSで用いられる仕組みで、Windowsではファイルハンドル(file handle)がほぼこれに相当する仕組みを提供する。

https://e-words.jp/w/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%82%BF.html#:~:text=%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%82%BF%E3%81%A8%E3%81%AF%E3%80%81%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0,%E3%82%89%E3%82%8C%E3%82%8B%E6%95%B4%E6%95%B0%E5%80%A4%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82

エラー発生現象の確認

下記手順でエラー原因を特定

  1. 現状のファイルディスクリプタの設定値を確認
  2. ビルドプロセスのPIDを確認
  3. ビルドプロセスの読み込みファイルの確認

ファイルディスクリプタの設定値の確認

ファイルディスクリプタの設定値は下記コマンドで確認

$ ulimit -n
1024

Amazon Linux 2 の初期値は 1024です。

ファイルディスクリプタの設定値を変更

ファイルディスクリプタの設定値は下記コマンドで変更

$ ulimit -n 4096

//確認
$ ulimit -n
4096

ビルドを実行しプロセスのIDを確認(PID)

ビルド実行

$npm run build
$yarn build
..etc

ビルドを実行しプロセスのIDは下記コマンドで確認

$ ps aux 
または
$ top

topコマンドで node コマンドのプロセス

 PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                                                                                              
 8544 ec2-user  20   0   11.1g 496704  34240 R 87.5 24.4   0:07.81 node                                                                                                                                                 
    1 root      20   0  123824   2760   2016 S  0.0  0.1   0:02.78 systemd

ビルドプロセスの読み込みファイルの確認

ビルド実行のプロセスが読み込んでいるファイル数の確認

$ lsof -p 8544 | wc -l
434

ここで、ファイル読み込み数が4096を超えた時点で、エラーが発生

$ lsof -p 8544 | wc -l
4122

再度 ファイルディスクリプタの設定値を変更

$ ulimit 65535
ulimit: open files: cannot modify limit: Operation not permitted

ulimit コマンドでは4096以上の設定が不可の模様

/etc/security/limits.conf に直接ファイルディスクリプタ上限値を設定

$sudo su -
#cd /etc/security/limits.conf

下記設定

* soft nofile 65536
* hard nofile 65536

再度ログインすると/etc/security/limits.conf の設定が反映

再度ビルドを実行

$yarn build

読み込みファイルが上限値に達すること無く終了。

参考:

https://stackoverflow.com/questions/11342167/how-to-increase-ulimit-on-amazon-ec2-instance

https://christina04.hatenablog.com/entry/how-to-change-file-descriptor-limit

https://www.soudegesu.com/linux/systemd_limits/

この記事のご感想やコメントはこちら

メールアドレスが公開されることはありません。 が付いている欄は必須項目です