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

Node.jsのEMFILE:ulimitを上げる前に記述子上限の所有者を特定する

失敗したプロセス、継承上限、記述子の増加を保存し、低い上限、リーク、同時実行の山、監視負荷を分けます。

オリジナル編集イラスト:シェル、サービス、プロセス、現在使用量の証拠を比較する。
オリジナル編集イラスト:上限変更前に記述子境界の所有者を特定する。 Watch at Ease

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が消え、説明可能な定常値へ戻ることが完了条件です。

オリジナル編集イラスト:低い上限、リーク、瞬間負荷、監視圧力を分ける。
オリジナル編集イラスト:一つのスナップショットで四つの対処を分ける。 Watch at Ease