そんな連絡を深夜に受けた経験がある人は少なくないだろう。プロセスを再起動すれば一時的に回復するが、数時間後にはまた同じ状態になる——この繰り返しが現場を消耗させる。
「ファイルが多すぎる=ディスクが溢れた」と思い込んで df コマンドを打ち、問題がないとわかると今度は古いログファイルを削除し始める——私自身、SE時代に同じ間違いを犯して2時間以上無駄にした。原因はファイルディスクリプタ(FD)の枯渇だ。「上限を上げれば解決」と思われがちだが、FDリークが原因の場合は上限を上げても焼け石に水になる。まず現状を正確に把握してから手を打つのが正解だ。
この記事では、FD枯渇の仕組みから調査コマンド、上限値の恒久設定、FDリークの特定まで、一連の対処手順を実機の出力例とあわせて解説する。RHEL 9.4 / Ubuntu 24.04 LTS で動作確認済み。
この記事のポイント
・/proc/sys/fs/file-nr でシステム全体のFD使用数を即座に把握できる
・lsof でFDを大量消費しているプロセスをPID別に特定できる
・limits.confとLimitNOFILEの2箇所を設定しないと恒久化されない
・上限を「unlimited」に設定するのは危険——必ず具体的な数値を入れる
・FDが時間とともに増え続ける場合はアプリのFDリークを疑う
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
SE時代に「Too many open files」で2時間右往左往した話
2004年、私がSEとして担当していたWebサーバーで起きた出来事だ。昼過ぎからアクセスが増えてきた頃、本番のApacheが断続的にエラーを返すようになった。ブラウザには「503 Service Unavailable」が表示され、上司から「早く直してくれ」と催促を受けながら焦って対応していた。
pingはサーバーに通る。SSHでログインもできる。ps コマンドでApacheのプロセスが動いていることも確認できる。なのにリクエストに応答しない。何が起きているのかまったくわからなかった。
先輩から「エラーログを見ろ」と言われて /var/log/httpd/error_log を開いたところ、次のようなメッセージが延々と並んでいた。
[Wed Apr 07 13:42:17 2004] [emerg] (24)Too many open files: Error getting accept lock. Exiting! [Wed Apr 07 13:42:18 2004] [emerg] (24)Too many open files: Error getting accept lock. Exiting! [Wed Apr 07 13:42:19 2004] [emerg] (24)Too many open files: Error getting accept lock. Exiting!
そのとき先輩に言われた一言が、「それはディスクの問題じゃない。ulimit を確認しろ」だった。
この一言で初めてファイルディスクリプタという概念を知った。原因が明確になった瞬間、2時間の右往左往が恥ずかしくなったのを今でも覚えている。それ以来、「Too many open files」が出たときは必ずulimitを最初に確認することを習慣にしている。
ファイルディスクリプタとは何か(なぜエラーが起きるのか)
Linuxではファイルを開くたびに、カーネルがプロセスに「ファイルディスクリプタ(FD)」という整数番号を割り当てる。ファイルだけでなく、ソケット・パイプ・デバイスなど、プロセスが「開いているもの」はすべてFDで管理される。・stdin(標準入力): FD 0
・stdout(標準出力): FD 1
・stderr(標準エラー出力): FD 2
・以降は open() や accept() のたびに 3、4、5…と割り当てられる
重要なのは、Linuxにおける「ファイル」の概念が非常に広いことだ。通常のテキストファイルだけでなく、以下のリソースもすべてFDを消費する。
・通常ファイル: テキストファイル、ログファイル、バイナリファイルなど
・ソケット: TCP/UDPによるネットワーク接続(HTTPリクエスト1件で1つ消費)
・パイプ: プロセス間でデータをやり取りするためのパイプ
・デバイスファイル: /dev/ 配下にあるデバイスへのアクセス
カーネルはFDの上限を2段階で管理している。
・プロセス単位の上限: 1プロセスが同時に開けるFDの最大数(ulimit -n で確認できる値)
・システム全体の上限: 全プロセス合計のFD使用数の上限(/proc/sys/fs/file-max で確認できる値)
プロセスが上限に達すると、新しくファイルやソケットを開こうとしたときにカーネルがEMFILEエラーを返す。これがアプリ側で「Too many open files」として表示される原因だ。
注意しなければならないのは、「ファイル」という名称に惑わされないことだ。Webサーバーがクライアントとの接続を1本確立するたびに、ソケット用のFDを1つ消費する。各接続で1つ、エラーログの書き込みで1つ、設定ファイルの読み込みで複数、といった具合にどんどん積み上がっていく。Linuxのデフォルト上限は「1プロセスあたり1024個」に設定されていることが多く、ある程度のアクセスが来るサーバーではすぐに壁にぶつかる数字だ。
セミナーで「なぜデフォルトが低いの?」と質問を受けることがある。理由は歴史的なもので、Linuxが設計された時代のシステムリソースに合わせた値が今に至るまで残っている。現代のサーバー運用者が意識して見直すべき設定のひとつだ。
まず現状を把握する(/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 # Apache/httpd のエラーログを直接確認する場合 grep -i "too many open" /var/log/httpd/error_log grep -i "too many open" /var/log/apache2/error.log
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
[Wed Mar 05 08:47:12 2003] [error] (24)Too many open files: accept client connection: (null) [Wed Mar 05 08:47:12 2003] [error] (24)Too many open files: accept client connection: (null) [Wed Mar 05 08:47:13 2003] [error] (24)Too many open files: couldn't create accept lock
2. /proc/sys/fs/file-nr でシステム全体のFD使用数を確認する
cat /proc/sys/fs/file-nr
34304 0 392328
・1列目(34304): 現在使用中のFD数(システム全体合計)
・2列目(0): 割り当て済みだが未使用のFD数(通常は0)
・3列目(392328): システム全体の最大FD数(fs.file-max の値)
1列目が3列目の値に近い場合はシステム全体の枯渇を疑う。1列目が少ないにもかかわらずエラーが出る場合は、特定プロセスのプロセス単位上限超過を疑う。
3. 特定プロセスのFD上限と現在値を確認する
# ソフトリミット(現在のセッションに適用されている上限値)を確認する ulimit -Sn # ハードリミット(一般ユーザー権限で設定できる最大値)を確認する ulimit -Hn # 特定プロセス(PID=4821)の上限を確認する cat /proc/4821/limits | grep "Max open files" # 現在そのプロセスが使っているFD数を確認する ls /proc/4821/fd | wc -l
・soft limit: 現在実際に適用されている上限値。ユーザーはhard limitを超えない範囲で自分で変更できる
・hard limit: 管理者(root)のみが変更できる上限値。ユーザーはこれを超えた値をsoft limitに設定することはできない
出力例(/proc/4821/limits):
Limit Soft Limit Hard Limit Units Max open files 1024 4096 files
プロセス別のFD使用数を調べる(lsof と /proc/PID/fd)
1. FDを多く使っているプロセスをランキングで把握する
# PID別のFD使用数ランキング(上位10プロセス) lsof 2>/dev/null | awk '{print $2}' | sort | uniq -c | sort -rn | head -10 # 特定ユーザー(例: nginx)が使っているFDの総数を確認する lsof -u nginx 2>/dev/null | wc -l
1823 4821 312 1234 241 5610 87 998
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
・IPv4/IPv6 が多い → ソケット(TCP接続)のclose漏れを疑う
・PIPE が多い → パイプのclose漏れを疑う
上記の例ではIPv4ソケットが1547個を占めており、TCPコネクションが積もっていると判断できる。Linux ポート確認の全コマンドで解説しているように、`lsof -i` でソケットの接続先や状態(ESTABLISHED/CLOSE_WAIT)を確認すると調査がさらに進む。
上限を一時的に引き上げる(ulimit -n と systemd の LimitNOFILE)
まず一時的に上限を上げてサービスを安定させてから、恒久設定に移る。1. ulimit -n で現在のシェルの上限を変更する
# すべてのリソース制限を一覧確認する(open files の行に注目) ulimit -a # FD上限を65535に変更する(現在のシェルとそこから起動したプロセスに適用) ulimit -n 65535 # 確認する ulimit -n
core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 15264 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 15264 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
2. systemdサービスは LimitNOFILE で設定する
nginxやMySQLなど、systemdで管理されているサービスはPAMを経由しないため limits.conf を読まない。ユニットファイルで個別に設定する必要がある。# ユニットファイルをオーバーライドで編集する(nginx の例) # 「systemctl edit」を使うと自動でdrop-inファイルが作成される systemctl edit nginx
[Service] LimitNOFILE=65535
あるいは設定ディレクトリを直接作成して追加する方法でも同じ効果が得られる:
# drop-inディレクトリを作成して設定ファイルを追加する(nginx の例) mkdir -p /etc/systemd/system/nginx.service.d/ cat > /etc/systemd/system/nginx.service.d/limits.conf << 'EOF' [Service] LimitNOFILE=65535 EOF
systemctl daemon-reload systemctl restart nginx # 反映確認(新PIDを確認してから実行する) cat /proc/$(pidof -s nginx)/limits | grep "Max open files"
Limit Soft Limit Hard Limit Units Max open files 65535 65535 files
LimitNOFILE=65535 LimitNOFILESoft=65535
上限を恒久的に変更する(limits.conf と sysctl fs.file-max)
1. /etc/security/limits.conf でプロセス上限を永続設定する
全ユーザーに適用する場合:# /etc/security/limits.conf に追記する * soft nofile 65535 * hard nofile 65535
nginx soft nofile 65535 nginx hard nofile 65535
重要: systemdで管理するサービス(nginx、MySQL等)はPAMを経由しないため、limits.conf の設定は効かない。systemdサービスは前節のLimitNOFILEで個別に設定する。「limits.confに設定したのに変わらない」という場合はほぼ間違いなくこのパターンだ。まずサービスの起動方法(systemd管理か否か)を確認してから設定を変えることが先決だ。
2. sysctl で fs.file-max(システム全体の上限)を変更する
# 現在値の確認 sysctl fs.file-max # 一時的な変更(再起動後に元に戻る) sysctl -w fs.file-max=1000000
# 設定ファイルを新規作成して永続化する 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の全サービスのデフォルト値を一括変更することもできる
4. 上限値はいくつに設定すべきか
セミナーで「どんな値を設定すればいいか?」とよく質問を受ける。現場で使っている目安を2点お伝えする。「unlimited」は設定しない
hard limitをunlimitedにすると、プロセスがFDを際限なく開き続けられるようになる。FDリーク(バグによって正しくクローズされない状態)が起きているプログラムがあった場合、メモリを食いつぶしてシステムがクラッシュする原因になる。必ず具体的な数値を設定すること。
ピーク値の2~3倍を目安にする
`ls /proc/PID/fd | wc -l` で実測した最大使用量が1,000であれば、2,048~4,096程度が適切だ。Webサーバーであれば最大同時接続数×2程度のマージンを持たせた値が目安になる。65535(64K近辺)はよく使われる設定値で、ほとんどのWebサービスにとっては十分な余裕がある。変更後は必ず `/proc/[PID]/limits` で設定が反映されたことを確認してから作業完了とすること。
FDリークを疑うときの調査手順
上限を引き上げても数時間後にまたエラーが出る場合は、アプリがFDをclose()せずに積み重ねている「FDリーク」を疑う。再起動直後はFD数が減り、時間とともに単調増加するパターンが典型的だ。1. watch コマンドでFD数の増加を監視する
# PID=4821のFD数を5秒ごとに監視する watch -n 5 "ls /proc/4821/fd | wc -l"
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
3. 緊急回避としての定期再起動
FDリークの根本修正に時間がかかる場合は、cron で定期的にサービスを再起動して延命する。# crontab -e で追加(毎日深夜3時に再起動する例) 0 3 * * * /usr/bin/systemctl restart myapp
本記事のまとめ
「Too many open files」の対処は、「現状把握 → 上限変更 → リーク調査」の3段階で進める。まずプロセス単位の枯渇かシステム全体の枯渇かを切り分け、原因に合わせた設定変更を行う。3,100名以上の受講生と向き合ってきた中で、障害対応が得意なエンジニアほど「確認の型」を持っているという共通点がある。対処で特につまずきやすい3点を押さえておこう:
・「ファイル」という名前に惑わされない: ネットワーク接続(ソケット)もパイプもFDで管理される。Webサーバーのアクセス集中でFDが枯渇するのはそのためだ
・サービスの起動方法を確認してから設定を変える: systemd管理のサービスにはlimits.confが効かない。LimitNOFILEをユニットファイルに設定する
・「設定した」で終わりにしない: 変更後は必ず /proc/[PID]/limits で反映を確認する
| やりたいこと | コマンド |
|---|---|
| システム全体のFD使用数を確認する | cat /proc/sys/fs/file-nr |
| システム全体の最大FD数を確認する | sysctl fs.file-max |
| プロセスのFD上限を確認する | cat /proc/PID/limits | grep "Max open files" |
| soft/hard limitを個別に確認する | ulimit -Sn / ulimit -Hn |
| 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上限を設定する | systemctl edit サービス名 で 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" |
・Linuxのポート確認コマンド|ss・lsofの使い方
・chkconfigとsystemctlの使い分け|サービスの自動起動設定
FDエラーを素早く解消できるのは、Linuxの仕組みを体系的に理解しているから
ulimitの変更方法は調べれば分かります。でも「なぜsystemdサービスはlimits.confを読まないのか」「FDリークとプロセス上限不足はどう見分けるのか」を現場で即答できますか?
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます