ようへいの日々精進XP

よかろうもん

ファイルディスクリプタについて

はじめに

とあるアプリケーションを利用していて 1 プロセスが同時に開くことが出来るファイルディスクリプタの数がテーマになって色々と調べたのでメモ。


参考


うんちく

Linux におけるファイルディスクプリタとは

  • プログラムがアクセスするファイルや標準入出力などをOSが識別するために用いる識別子

制限

  • 1 プロセスで開くことが出来るディスクプリタの数は 1024
  • OS 全体で開くことが出来る数は /proc/sys/fs/file-max を確認する

実例

Apache の場合

  • Prefork MPM の場合 1プロセスあたりのファイルディスクプリタオープン数はそこまで増えないので問題にならない
  • Worker MPM の場合には 1 スレッドで多くのファイルディスクプリタを開くのでファイルディスクリプタの上限が問題になることがある

確認

OS 全体の最大値を確認

cat /proc/sys/fs/file-max

プロセス単位の最大値を確認

cat /proc/${PID}/limits

ちなみに CoreOS 上で起動している Docker コンテナに関しては以下のような感じ。

f:id:inokara:20130928051059p:plain


調整

ファイルディスクリプタのオープン数の上限を調整する為にいくつかの方法がある。また、PAM が通ってかつ、pam_limits.so が有効である場合のみ /etc/security/limits.conf への設定が有効になる等、色々と気を使わないといけないことがあるみたい。

ulimit コマンドで指定する

ulimit -n ${NUM}

即反映だが、OS を再起動してしまったりすると設定は失われてしまう。

/etc/security/limits.conf に記述する

以下のように適用するユーザー(${user})、SOFTHARD のリミットをそれぞれ設定(設定しない場合には - を設定) して、値(${NUM})を設定する。

${user} ${soft} ${hard} ${NUM}

また、/etc/security/limits.d/ 以下にアプリケーション毎、ユーザー毎に設定しても良いと思われる。

/etc/security/limits.d/hoge.conf

OS 起動時に実行されるアプリケーション等の場合

やり方は一つではないと思われるが、init スクリプトに直接設定する方法を試した。

--- /tmp/nginx  2013-09-26 09:24:53.633757188 +0000
+++ /etc/init.d/nginx   2013-09-26 09:26:19.129623273 +0000
@@ -44,6 +44,7 @@
                        # Set the ulimits
                        ulimit $ULIMIT
                fi
+               ulimit -n 2048
                start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \
                    --exec $DAEMON -- $DAEMON_OPTS || true
                echo "$NAME."

上記は nginxinit スクリプト。幸い ubuntuapt-get でインストールした nginx/etc/default/nginxulimit の設定が出来るので、上記のように記載する必要は無いが、今回はあえて直書きした。

上記の状態で nginx を起動してファイルディスクリプタのオープン数の上限を確認すると以下のようになっている。

f:id:inokara:20130928060116p:plain


まとめ

  • 奥深い