科技 · 實用指南
Node.js EMFILE:提高 ulimit 前先找出檔案描述符限制的擁有者
保存失敗程序、繼承限制與描述符成長,再區分低上限、洩漏、並行峰值與監視器壓力。

EMFILE 先是擁有權問題,之後才是調校問題。互動 shell、systemd 服務與重啟程序可能有不同證據;重啟前先保存失敗 PID。
重啟前固定失敗程序
記錄命令或服務、父啟動器、PID、時間戳與第一條 EMFILE 堆疊。不要先重啟或重裝依賴;它們會清空描述符表,掩蓋計數是穩定、持續增加或短時尖峰。
讀取程序實際繼承的限制
在 Linux 讀取 /proc/PID/limits 的 Max open files,並與互動 shell 的 ulimit -Sn、-Hn 比較。子程序繼承父程序限制;systemd 啟動服務後才改 shell,不會回溯改變服務。
量測目前描述符與成長
統計 /proc/PID/fd 並多次取樣,將目標分為一般檔案、socket、pipe 與匿名描述符。穩定貼近上限支持限制分支;持續上升支持洩漏;並行工作時尖峰支持併發分支。
分開監視器壓力與一般檔案
以 fs.watch 或 FSEvent 結尾的堆疊只指出監視器表面,不證明通用修復。比較監視範圍、忽略目錄與程序描述符;Linux 還需區分程序描述符和獨立 inotify 計帳。
只修改正確擁有者
服務若繼承過低軟限制,在其啟動器或單元調整並重啟該服務。計數只升不降就關閉洩漏的檔案、socket 或監視器;峰值則限制併發並及時關閉。別修改無關 shell 後宣稱修復。
在原啟動器下證明完成
從相同 shell、管理器、CI 或服務單元重跑相同負載,保存新 PID 限制、峰值與工作後基線。完成代表 EMFILE 消失且計數回到可解釋穩態,不只是重啟後一次通過。
