テクノロジー · 実用ガイド
ulimit を上げても Too many open files?Linux サービスが当たった上限を証明する
現在のシェルの ulimit は実行中サービスの証拠ではありません。失敗した PID から RLIMIT_NOFILE、システムのファイル表、inotify を分けます。

Linux の「Too many open files」だけでは、どの上限が失敗したかは分かりません。EMFILE は多くの場合プロセスの RLIMIT_NOFILE、ENFILE はシステム全体のファイル表を示し、inotify もユーザーのインスタンス上限で EMFILE を返します。
現在のシェルで高い ulimit が表示されても、既存サービスの制限は証明できません。失敗時刻と PID を保存し、そのプロセスが継承した制限と FD 数を読み、システムと inotify の分岐も確認します。
1. シェルではなく失敗したプロセスを保存する
再起動前にエラー時刻とサービス PID を記録します。systemd なら systemctl show UNIT -p MainPID -p LimitNOFILE、/proc/PID/limits、/proc/PID/fd を確認します。後から管理シェルで実行した ulimit -n はそのシェルの値です。
soft と hard を分け、FD 数を soft 値と比較し、readlink で対象を抽出確認します。lsof -u USER の合計を一つのプロセスの数として扱わないでください。
2. EMFILE、ENFILE、inotify を分ける
errno が得られるなら、EMFILE は通常 RLIMIT_NOFILE、ENFILE はシステムのファイル表です。file-nr と file-max を比較し、カーネルログの file-max reached を確認します。一般的な文言だけで file-max を上げません。
watch 作成時の失敗や watch を示すログなら inotify を確認します。inotify_init の EMFILE はユーザーのインスタンス上限とプロセス FD 上限の両方があり、max_user_instances と max_user_watches は別です。
3. サービスの継承元を追う
PAM、シェル、コンテナ、ランチャー、systemd は別の継承経路です。systemd サービスでは読み込まれたユニットと drop-in を確認し、LimitNOFILE の単一値または soft:hard を使います。
巨大な値を全サービスへコピーしないでください。systemd は select 使用アプリが 1023 超の FD を扱えないと警告します。対応を確認し、ローカル drop-in と復元用の旧値を使います。
4. 正常な同時実行とリークを分ける
一回の数では正常性を判断できません。同じ PID を同等負荷で繰り返し測り、socket、pipe、通常ファイル、匿名 FD に分けてアプリ指標と比較します。作業終了後も減らず増え続けるならリークの手掛かりです。
再起動は一時的に数を下げても原因を直しません。事前証拠を残し、有界な定常状態を探します。特定種類だけ異常成長するなら上限より所有者を直します。
5. 一つの所有者だけを変更し、新しい子を証明する
証拠が示した層だけを変更します。プロセス制限はサービス/ランチャー、リークはアプリ、システム表は容量評価、inotify は消費者の確認が先です。必要なら一度だけ再起動し、新 PID と制限を再読します。
成功とは、対象が意図した制限を継承し、実負荷で余裕があり、元のエラーが消えることです。errno 不明、所有者不明、nr_open 超過、無制限リークを隠す変更なら中止してエスカレーションします。
