テクノロジー · 実用ガイド

ulimit を上げても Too many open files?Linux サービスが当たった上限を証明する

現在のシェルの ulimit は実行中サービスの証拠ではありません。失敗した PID から RLIMIT_NOFILE、システムのファイル表、inotify を分けます。

プロセス FD、システムファイル表、inotify 上限を分けるオリジナル図
オリジナル概念図:同じメッセージでも三つの証拠経路があります。 Watch at Ease

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 超過、無制限リークを隠す変更なら中止してエスカレーションします。

Linux サービスの FD 制限を証明するオリジナルチェック表
オリジナル概念図:継承上限、現在圧力、競合上限を確認します。 Watch at Ease