テクノロジー · 実用ガイド
Node.jsのEMFILE:ulimitを上げる前に記述子上限の所有者を特定する
失敗したプロセス、継承上限、記述子の増加を保存し、低い上限、リーク、同時実行の山、監視負荷を分けます。

EMFILEは調整より先に所有者を特定する問題です。対話シェル、systemdサービス、再起動後のプロセスでは証拠が異なるため、再起動前にPIDを保存します。
再起動前に失敗プロセスを固定する
正確なコマンドまたはサービス、親ランチャー、PID、時刻、最初のEMFILEスタックを記録します。再起動や依存関係の再導入を先に行うと、記述子表が消え、安定・増加・瞬間的な山の区別が失われます。
実際に継承した上限を読む
Linuxでは /proc/PID/limits の Max open files を読み、対話シェルの ulimit -Sn と -Hn と比較します。子は親の上限を継承するため、systemdが起動した後のシェル変更はサービスに遡及しません。
現在の記述子と増加を測る
/proc/PID/fd を複数回数え、通常ファイル、ソケット、パイプ、匿名記述子に分類します。一定の上限付近なら制限、増え続けるならリーク、並列作業時だけの山なら同時実行を疑います。
監視負荷を通常ファイルから分ける
fs.watchやFSEventで終わるスタックは監視面を示すだけで、万能修正の証拠ではありません。監視範囲、除外ディレクトリ、プロセス記述子数を比較し、Linuxではinotifyの別会計も区別します。
正しい所有者を一度だけ変更する
サービスのソフト上限が不必要に低いならランチャーやユニットで変更し、そのサービスを再起動します。増え続けるなら未閉鎖のファイルやソケット、監視を直し、山なら同時実行を制限します。無関係なシェル変更を修正と呼びません。
元のランチャーで完了を証明する
同じシェル、スーパーバイザー、CI、サービスユニットから同じ負荷を再実行し、新PIDの上限、ピーク、終了後の基準値を保存します。EMFILEが消え、説明可能な定常値へ戻ることが完了条件です。
