ざる魂

真似ぶ魂、学ぶの本質。知られざる我が魂

ファイルオープン数が上限値に達した

CentOSで「too many files」なるエラーが多発したのでその対応策をメモしておく。

下記を参考にした。

確認方法

ファイル上限値の確認コマンドは以下。

$ cat /proc/sys/fs/file-nr
1792    0       566699

左から順に

  • 今までにオープンしたことのあるファイルの最大数
  • 現在オープンしているファイルの総数
  • オープン可能なファイル数の上限

となる。

一時的な設定方法

システム全体

現状のファイルディスクリプタの上限値を確認

$ cat /proc/sys/fs/file-nr
1792    0       566699

一時的にファイルディスクリプタの上限値を変更する。

$ /sbin/sysctl -w fs.file-max = 1234567

設定値の確認

$ cat /proc/sys/fs/file-nr
1216    0       1234567

ユーザ毎(カレントユーザ)

現在のセッション(自分が起動したプロセス)に対して、 ファイルディスクリプタ上限値を設定するには、 ulimit を使用する。

ulimitはユーザに対していろいろな制限を設定するコマンド。 ulimit -a で全ての設定値を確認できる。

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 114688
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 114688
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

ファイルディスクリプタの上限値を設定するには、 ulimit -n N でファイルディスクリプタ上限をN個に変更できる。

まず現状のファイルディスクリプタの上限値を確認する。

# (open filesが該当)
$ ulimit -n
1024

下記は、Nを2048個にする例。

$ ulimit -n 2048
-bash: ulimit: open files: cannot modify limit: 許可されていない操作です
$ sudo ulimit -n 2048
sudo: ulimit: command not found

残念ながら一般ユーザ実行すると失敗する(sudoでも実行できない)。 rootユーザで実行しなくてはならない。

$ sudo su
# ulimit -n 2048
$ ulimit -n
2048

ただし直接rootになることは禁止されている環境も多いため、実質この方法は実施できない。

恒久的な設定方法

一時的な方法では、OSを再起動すると初期値に戻ってしまう。 これを防ぐためには、設定ファイルに直接記述する。

設定対象のファイルは以下のとおり。

/etc/sysctl.conf
システム全体のファイルオープン数
/etc/security/limits.conf
アカウント毎のファイルオープン数

設定前にバックアップしておく。

sudo cp /etc/security/limits.conf /etc/security/limits.conf.orig
sudo cp /etc/sysctl.conf /etc/sysctl.conf.orig

sysctl.conf

まず現在値を確認。

$ cat /proc/sys/fs/file-nr
1792    0       566699

sysctl.confを編集。

$ sudo vi /etc/sysctl.conf
fs.file-max = 1232457
# FORMAT
# fs.file-max = N :システム全体のファイルディスクリプタの上限
# kernel.threads-max = N :システム全体のプロセス数の上限

設定ファイルの内容を反映させる。

$ sudo /sbin/sysctl -p

変更を確認。

$ cat /proc/sys/fs/file-nr
1792    0       1234567

ちなみに上限値は下記でも確認できる。

$ /sbin/sysctl fs.file-max
fs.file-max = 593544

limits.conf

注意点として、limits.confに設定した値は、ログインしないdameonプロセスには効かないとのこと。

/etc/init.d/配下から起動する場合は、その起動スクリプト内に ulimit -n <num> を記述する必要がある。

limits.confは設定値は、ログインしたユーザのセッション内で有効になる。

$ sudo vi /etc/security/limits.conf
mikio soft nofile 2048
mikio hard nofile 2048
# FORMAT
# <USER> <soft|hard> <nofile|noproc> <設定数>
# soft:一般ユーザが設定可能な上限値(ulimit -nのことかな?)
# hard:ルートユーザが設定可能な上限値
# nofile: ファイルディスクリプタの上限値
# noproc: プロセス(スレッド)の上限値

すぐに反映させるには、一度ログアウトして、そこから対象プロセス(tomcatやapache)を再起動する。