LinuxでToo many open filesエラーが出た時の対処法|ファイルディスクリプタ枯渇の調査からulimit・sysctl設定まで

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtips, Linuxトラブルシューティング > LinuxでToo many open filesエラーが出た時の対処法|ファイルディスクリプタ枯渇の調査からulimit・sysctl設定まで
「サーバーが落ちた。ログに『Too many open files』が大量に出ている。」
そんな連絡を深夜に受けた経験がある人は少なくないだろう。プロセスを再起動すれば一時的に回復するが、数時間後にはまた同じ状態になる——この繰り返しが現場を消耗させる。

原因はファイルディスクリプタ(FD)の枯渇だ。「上限を上げれば解決」と思われがちだが、FDリークが原因の場合は上限を上げても焼け石に水になる。まず現状を正確に把握してから手を打つのが正解だ。

この記事では、FD枯渇の仕組みから調査コマンド、上限値の恒久設定、FDリークの特定まで、一連の対処手順を実機の出力例とあわせて解説する。RHEL 9.4 / Ubuntu 24.04 LTS で動作確認済み。

この記事のポイント

・/proc/sys/fs/file-nr でシステム全体のFD使用数を即座に把握できる
・lsof でFDを大量消費しているプロセスをPID別に特定できる
・limits.confとLimitNOFILEの2箇所を設定しないと恒久化されない
・FDが時間とともに増え続ける場合はアプリのFDリークを疑う


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

ファイルディスクリプタとは何か(なぜエラーが起きるのか)

Linuxではファイルを開くたびに、カーネルがプロセスに「ファイルディスクリプタ(FD)」という整数番号を割り当てる。ファイルだけでなく、ソケット・パイプ・デバイスなど、プロセスが「開いているもの」はすべてFDで管理される。

・stdin(標準入力): FD 0
・stdout(標準出力): FD 1
・stderr(標準エラー出力): FD 2
・以降は open() や accept() のたびに 3、4、5…と割り当てられる

カーネルはFDの上限を2段階で管理している。

・プロセス単位の上限: 1プロセスが同時に開けるFDの最大数(ulimit -n で確認できる値)
・システム全体の上限: 全プロセス合計のFD使用数の上限(/proc/sys/fs/file-max で確認できる値)

プロセスが上限に達すると、新しくファイルやソケットを開こうとしたときにカーネルがEMFILEエラーを返す。これがアプリ側で「Too many open files」として表示される原因だ。

まず現状を把握する(/proc/sys/fs/file-nr と journalctl)

エラーが出たら、「プロセス単位の上限超過か」「システム全体の上限超過か」を最初に切り分ける。

1. journalctl でエラーの発生時刻とプロセスを確認する

どのプロセスがいつエラーを出したかを最初に把握する。

# 直近1時間のToo many open files関連のログを確認 journalctl -xe --since "1 hour ago" | grep -i "too many open" # RHEL系は /var/log/messages でも確認できる grep -i "too many open" /var/log/messages

実際の出力例(RHEL 9.4):

Aug 22 03:17:42 web01 nginx[4821]: 2026/08/22 03:17:42 [alert] 4821#4821: socket() failed (24: Too many open files) while accepting new connection on 0.0.0.0:443

プロセス名(ここではnginx)とPID(4821)がわかる。次のステップでそのプロセスのFD使用状況を掘り下げる。

2. /proc/sys/fs/file-nr でシステム全体のFD使用数を確認する

cat /proc/sys/fs/file-nr

出力例:

34304 0 392328

3列の意味:

・1列目(34304): 現在使用中のFD数(システム全体合計)
・2列目(0): 割り当て済みだが未使用のFD数(通常は0)
・3列目(392328): システム全体の最大FD数(fs.file-max の値)

1列目が3列目の値に近い場合はシステム全体の枯渇を疑う。1列目が少ないにもかかわらずエラーが出る場合は、特定プロセスのプロセス単位上限超過を疑う。

3. 特定プロセスのFD上限と現在値を確認する

# 現在のシェルのFD上限を確認 ulimit -n # 特定プロセス(PID=4821)の上限を確認 cat /proc/4821/limits | grep "Max open files" # 現在そのプロセスが使っているFD数を確認 ls /proc/4821/fd | wc -l

出力例(/proc/4821/limits):

Limit Soft Limit Hard Limit Units Max open files 1024 4096 files

「Soft Limit(1024)」が現在の実効上限、「Hard Limit(4096)」が一般ユーザー権限で設定できる上限の最大値だ。ulimit -n で変更できるのはSoft Limitの範囲内に限られる。

プロセス別のFD使用数を調べる(lsof と /proc/PID/fd)

1. FDを多く使っているプロセスをランキングで把握する

# PID別のFD使用数ランキング(上位10プロセス) lsof 2>/dev/null | awk '{print $2}' | sort | uniq -c | sort -rn | head -10

出力例:

1823 4821 312 1234 241 5610 87 998

1列目がFD数、2列目がPIDだ。PID 4821 が1823個のFDを持っており突出している。先ほどのjournalctlで確認したPIDと一致すれば、そのプロセスが原因と断定できる。

2. 特定プロセスのFD種別を確認する

FDが何に使われているか(ファイル・ソケット・パイプ)を種別ごとに集計すると、原因の当たりがつきやすい。

# PID=4821のFDを種別ごとに集計 lsof -p 4821 2>/dev/null | awk '{print $5}' | sort | uniq -c | sort -rn

出力例:

1547 IPv4 189 REG 56 PIPE 17 IPv6 14 CHR

・REG(Regular file)が多い → ファイルのclose()忘れを疑う
・IPv4/IPv6 が多い → ソケット(TCP接続)のclose漏れを疑う
・PIPE が多い → パイプのclose漏れを疑う

上記の例ではIPv4ソケットが1547個を占めており、TCPコネクションが積もっていると判断できる。Linux ポート確認の全コマンドで解説しているように、`lsof -i` でソケットの接続先や状態(ESTABLISHED/CLOSE_WAIT)を確認すると調査がさらに進む。

上限を一時的に引き上げる(ulimit -n と systemd の LimitNOFILE)

まず一時的に上限を上げてサービスを安定させてから、恒久設定に移る。

1. ulimit -n で現在のシェルの上限を変更する

# FD上限を65535に変更(現在のシェルとそこから起動したプロセスに適用) ulimit -n 65535 # 確認 ulimit -n

ulimit -n での変更は現在のシェルにしか効かない。既に起動済みのサービスには適用されないため、サービスの再起動が必要になる。

2. systemdサービスは LimitNOFILE で設定する

nginxやMySQLなど、systemdで管理されているサービスはPAMを経由しないため limits.conf を読まない。ユニットファイルで個別に設定する必要がある。

# ユニットファイルをオーバーライドで編集する(nginx の例) systemctl edit nginx

エディタが開いたら以下を追記して保存する:

[Service] LimitNOFILE=65535

設定を反映してサービスを再起動する:

systemctl daemon-reload systemctl restart nginx # 反映確認(新PIDを確認してから実行する) cat /proc/$(pidof -s nginx)/limits | grep "Max open files"

出力例:

Max open files 65535 65535 files

Soft/Hard ともに65535になっていれば設定が反映されている。

上限を恒久的に変更する(limits.conf と sysctl fs.file-max)

1. /etc/security/limits.conf でプロセス上限を永続設定する

全ユーザーに適用する場合:

# /etc/security/limits.conf に追記する * soft nofile 65535 * hard nofile 65535

特定ユーザー(例: nginx)だけに設定する場合:

nginx soft nofile 65535 nginx hard nofile 65535

この設定はログアウト・ログイン後に適用される。既存のセッションには影響しないことに注意する。

重要: systemdで管理するサービス(nginx、MySQL等)はPAMを経由しないため、limits.conf の設定は効かない。systemdサービスは前節のLimitNOFILEで個別に設定する。

2. sysctl で fs.file-max(システム全体の上限)を変更する

# 現在値の確認 sysctl fs.file-max # 一時的な変更(再起動後に元に戻る) sysctl -w fs.file-max=1000000

永続化するには /etc/sysctl.d/ に設定ファイルを作成する:

# 設定ファイルを新規作成して永続化する echo "fs.file-max = 1000000" | tee /etc/sysctl.d/99-filemax.conf # 即時反映 sysctl -p /etc/sysctl.d/99-filemax.conf # 確認 sysctl fs.file-max

出力例:

fs.file-max = 1000000

3. 設定の優先順と落とし穴

混乱しやすいポイントをまとめる:

・SSHでログインしたシェルなど、PAM経由のプロセス: limits.conf が有効
・systemdで管理されるサービス: limits.conf は無効。LimitNOFILE をユニットファイルに設定する
・limits.conf を変更してもsysctl fs.file-max が低ければシステム全体で詰まる
・/etc/systemd/system.conf の DefaultLimitNOFILE でsystemdの全サービスのデフォルト値を一括変更することもできる

FDリークを疑うときの調査手順

上限を引き上げても数時間後にまたエラーが出る場合は、アプリがFDをclose()せずに積み重ねている「FDリーク」を疑う。再起動直後はFD数が減り、時間とともに単調増加するパターンが典型的だ。

1. watch コマンドでFD数の増加を監視する

# PID=4821のFD数を5秒ごとに監視する watch -n 5 "ls /proc/4821/fd | wc -l"

正常なプロセスはFD数が上下しながら一定範囲に収まる。リークがある場合は5秒ごとに単調増加し続け、上限に達するまで止まらない。

2. FDの種別で原因を絞る

# 1分間隔でFD種別の集計を記録する(Ctrl+C で停止) while true; do echo "=== $(date) ===" lsof -p 4821 2>/dev/null | awk '{print $5}' | sort | uniq -c | sort -rn | head -5 sleep 60 done

どの種別(REG/IPv4/PIPE)が増え続けているかを記録し、対応するコードの箇所を開発チームに共有する。

3. 緊急回避としての定期再起動

FDリークの根本修正に時間がかかる場合は、cron で定期的にサービスを再起動して延命する。

# crontab -e で追加(毎日深夜3時に再起動する例) 0 3 * * * /usr/bin/systemctl restart myapp

あくまでも一時対応だ。根本原因(アプリのFDリーク)の修正を優先すること。

本記事のまとめ

「Too many open files」の対処は、「現状把握 → 上限変更 → リーク調査」の3段階で進める。まずプロセス単位の枯渇かシステム全体の枯渇かを切り分け、原因に合わせた設定変更を行う。

やりたいこと コマンド
システム全体のFD使用数を確認する cat /proc/sys/fs/file-nr
システム全体の最大FD数を確認する sysctl fs.file-max
プロセスのFD上限を確認する cat /proc/PID/limits | grep "Max open files"
PID別のFD使用数ランキングを出す lsof 2>/dev/null | awk '{print $2}' | sort | uniq -c | sort -rn | head -10
特定プロセスのFD数を確認する ls /proc/PID/fd | wc -l
FD上限を一時的に変更する(シェル) ulimit -n 65535
systemdサービスのFD上限を設定する ユニットファイルに LimitNOFILE=65535 を追記
FD上限を永続設定する(PAM経由プロセス) /etc/security/limits.conf に * soft nofile 65535 を追記
システム全体の上限を永続設定する /etc/sysctl.d/99-filemax.conf に fs.file-max = 1000000 を追記
FDリークの有無を監視する watch -n 5 "ls /proc/PID/fd | wc -l"

FDエラーを素早く解消できるのは、Linuxの仕組みを体系的に理解しているから

ulimitの変更方法は調べれば分かります。でも「なぜsystemdサービスはlimits.confを読まないのか」「FDリークとプロセス上限不足はどう見分けるのか」を現場で即答できますか?
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。