EMFILE(Too many open files)
「Too many open files」でプロセスが突然詰まる原因を、fdリーク・ソケット枯渇・ulimit不足に切り分けて即特定。lsofと/proc、ソフト/ハードリミットの正しい上げ方まで持ち帰れる。
- EMFILEは1プロセスが開けるファイルディスクリプタ(fd)の上限(RLIMIT_NOFILE=ulimit -n)に達した合図。ファイル・ソケット・パイプ・epollはすべてfdを消費する。
- 原因の大半はcloseし忘れによるfdリークで、時間とともにfd数が単調増加する。次いでソケット同時接続過多、ulimitが低すぎる設定の3つが定番。
- 診断はlsof -p PIDと/proc/PID/fdで実数を、ulimit -nで上限を確認。恒久対処はsystemd LimitNOFILEやlimits.confでハードリミットごと引き上げ、リークは根治する。
一言でいうと(このエラーが何を意味するか)
Too many open files(errno = EMFILE)は、1つのプロセスが同時に開けるファイルディスクリプタ(fd)の上限に達したという意味です。Linux/Unix では、通常のファイルだけでなく ソケット・パイプ・イベント通知(epoll/eventfd)・inotify・デバイスもすべて fd として数えられます。この上限は RLIMIT_NOFILE というリソース制限で、シェルからは ulimit -n で見えます。
open()・socket()・accept()・pipe() などがこの上限を超えて新しい fd を要求すると、カーネルは fd を割り当てず EMFILE を返します。アプリ側では「ファイルが開けない」「接続を受け付けられない」「ログが書けない」といった形で表面化します。
EMFILE(Too many open files)はそのプロセスの上限超過です。よく似た ENFILE(Too many open files in system)はシステム全体の上限(/proc/sys/fs/file-max や file-nr)超過で、原因も対処場所も異なります。まず errno がどちらかを確認してください。
横にスクロール
よくある原因(複数を具体的に、頻度順)
原因は次の順で多く、切り分けの見当をつける材料になります。
| 原因 | 典型的な兆候 | fd数の推移 |
|---|---|---|
| fdリーク(close漏れ) | 起動直後は正常、稼働時間に比例して悪化・再起動で一旦回復 | 単調増加し続ける |
| ソケット同時接続過多 | 接続数ピーク時だけ発生、accept失敗が集中 | 負荷に連動して上下する |
| ulimitが低すぎ | 起動直後や軽負荷でも即EMFILE | 上限が低く常に頭打ち |
| fdを消費するライブラリ | watcher/接続プールが接続ごとにfdを保持 | 設定値ぶんだけ高止まり |
-
fdリーク(close漏れ)が最頻。開いたファイル・ソケット・コネクションを閉じずに参照だけ捨てると、GC がある言語でもファイナライザ実行までfdが残り、実質リークになります。例外パスで
close()を通らない、コネクションプールが接続を返却しない、といった実装ミスが典型です。稼働時間に比例して悪化し、再起動で一旦直るのが特徴です。 -
ソケットの同時接続過多。1接続=1fd なので、C10K 級の常時接続サーバーや、外部 API への並行リクエスト、大量の keep-alive がそのまま fd 消費になります。なお
close()済みでTIME_WAIT状態にあるソケットは fd を解放済みで(占有するのはカーネル側の一時ソケットとポート/タプルのみ)、fd 数には計上されません。短命接続を高頻度で開閉する設計では、TIME_WAIT より先に「開いている fd のピーク」が上限に触れます。 -
ulimit が低すぎる。多くのディストリの既定ソフトリミットは 1024 で、接続の多いサーバーには小さすぎます。アプリを起動したシェル/サービスにこの低い値が継承されると、リークが無くても即上限に達します。
-
ライブラリ・ランタイム由来の消費。ファイル監視(inotify watch も fd)、DB 接続プールの最大数、Java の NIO セレクタなどが、設定値ぶんの fd を恒常的に確保します。
診断の手順(切り分け方・見るべきログ/コマンド)
まず「上限」と「実数」の両方を測り、実数が時間とともに増え続けるか(=リーク)を見ます。
現在の上限(ソフト/ハード)を確認します。
ulimit -Sn # ソフトリミット(現に効いている値)
ulimit -Hn # ハードリミット(ソフトを上げられる上限)
動いているプロセスに実際に効いている値は、シェルの ulimit ではなく対象プロセスの limits を見ます(サービスは別の環境で起動されているため)。
cat /proc/<PID>/limits | grep 'open files'
# Max open files <soft> <hard> files
開いている fd の実数を数えます。/proc は追加ツール不要で確実です。
ls /proc/<PID>/fd | wc -l # そのプロセスの現在のfd数
lsof -p <PID> | wc -l # lsofでも可(ヘッダ1行ぶん多い)
何を開いているかの内訳を見れば、リーク源が特定できます。同じパスやソケットが大量に並んでいれば close 漏れの疑いが濃厚です。
lsof -p <PID> | awk '{print $5, $9}' | sort | uniq -c | sort -rn | head
# TYPE と NAME で集計。REG(通常ファイル)/IPv4/sock が突出していないか
数分おきに ls /proc/<PID>/fd | wc -l を取り、負荷が一定なのに数が減らず増え続けるならリークです。負荷に連動して上下するだけなら、リークではなく上限不足かピーク設計の問題です。この一手で原因分類が決まります。
システム全体の逼迫(ENFILE 疑い)も併せて確認します。
cat /proc/sys/fs/file-nr # 割当済み 未使用 上限(file-max)
sysctl fs.file-max # システム全体の上限
解決と予防(対処と再発防止)
対処は「上限の引き上げ」と「リークの根治」の2軸です。上限引き上げは応急・恒久の両面で有効ですが、リークがあるなら上限を上げても到達時刻を遅らせるだけで、必ず根治が要ります。
恒久的に上限を上げる(systemd 管理サービス)。最も確実な指定先です。ソフトとハードを両方書きます。
# /etc/systemd/system/<service>.service.d/override.conf
[Service]
LimitNOFILE=1048576
systemctl daemon-reload
systemctl restart <service>
cat /proc/$(pidof <proc>)/limits | grep 'open files' # 反映を確認
ログインセッション/非 systemd 環境では PAM の limits で設定します。ハードリミットも上げないと、ソフトをそこまで引き上げられません。
# /etc/security/limits.conf (または /etc/security/limits.d/*.conf)
appuser soft nofile 1048576
appuser hard nofile 1048576
ソフトリミットはプロセス自身が setrlimit() で ハードリミットまで引き上げられます。多くのサーバーソフトが起動時にこれを行うため、ハードリミットを十分高くしておくのが実務上の勘所です。逆にハードリミットは root(CAP_SYS_RESOURCE)でしか上げられません。
EMFILE への短絡的対応は ulimit の引き上げですが、リーク性のバグを放置したまま上限だけ上げると、障害が「毎日」から「毎週」に伸びるだけで、より読みにくい間欠障害に化けます。fd数が単調増加していた場合は、上限引き上げと並行してコードの close 漏れを必ず塞いでください。
リークの根治は、確保した fd を確実に閉じることに尽きます。例外時も閉じられるよう、言語標準の後始末構文(try-with-resources/defer/with/using)で必ず包み、コネクションはプールへ確実に返却します。接続過多が原因なら、プールの上限設定・keep-alive の見直し・接続の再利用による開閉頻度の抑制で、開いている fd のピークを平準化します。
- EMFILE=プロセス単位(RLIMIT_NOFILE / ulimit -n)、ENFILE=システム単位(fs.file-max)
- ソケット・パイプ・epoll・inotify も fd を消費する(通常ファイルだけではない)
- ソフトリミットは自プロセスがハードリミットまで setrlimit で上げられる。ハードリミット引き上げは要 root
- リーク判定は「負荷一定でfd数が単調増加するか」。上限引き上げはリークを根治しない
fd を含むプロセス/リソース制限とカーネルの仕組みはOSを、ソケット・keep-alive・TIME_WAIT の挙動はネットワークを、接続プールやリソース解放を含む堅牢な実装作法はプログラミングを参照してください。
エラー辞典の記事ガイド
EMFILE(Too many open files)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
Linux
比較で見る軸
難易度: advanced / カテゴリ: エラー辞典 / タグ数: 6
導入後に効く点
原因の大半はcloseし忘れによるfdリークで、時間とともにfd数が単調増加する。次いでソケット同時接続過多、ulimitが低すぎる設定の3つが定番。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- エラー辞典
- タグ数
- 6
判断チェックリスト
- 自社の用途が「Linux / ファイルディスクリプタ」に近いか確認する。
- 強みである「EMFILEは1プロセスが開けるファイルディスクリプタ(fd)の上限(RLIMIT_NOFILE=ulimit -n)に達した合図。ファイル・ソケット・パイプ・epollはすべてfdを消費する。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。