🐧 Linux 総合学習プラットフォーム
プロセス監視/障害対応 ・ 中級

開いているファイル・ポートの確認

Linuxではファイルもソケットも「ファイルディスクリプタ」として扱われ、lsof で誰が何を開いているかを一覧できます。lsof -i で開いているネットワーク接続、lsof でディレクトリ配下のファイルを掴んでいるプロセス、を調べられます。プロセスが開けるファイル数には上限があり、上限に達すると「Too many open files」エラーが出ます。ss はソケット専用の高速ツールで、待ち受けポートや確立中の接続をすばやく確認できます。

Linuxには「すべてはファイルである」という設計思想があります。普通のテキストファイルや画像はもちろん、ハードウェアへの入り口や、プロセス間の通信路、そしてネットワーク接続までもが、ファイルと同じ仕組みで扱われます。プロセスがこうした対象を開くと、それぞれに「ファイルディスクリプタ」という管理番号が割り当てられます。ファイルディスクリプタとは、プロセスが今どのファイルやソケット(通信の出入り口)を開いているかを管理する整理番号のことです。この考え方を押さえると、ファイルとネットワークを同じ道具で調べられるようになり、障害調査の幅が大きく広がります。ここでは、開いているものを一覧する lsof と、ソケット専用の高速ツール ss を扱います。

lsof で「誰が何を開いているか」を見る

lsof は list open files の略で、その名のとおり、システム上で開かれているファイルを一覧するコマンドです。「すべてはファイル」なので、lsof で見えるのは通常ファイルだけでなく、ディレクトリ、ライブラリ、デバイス、ソケットなど多岐にわたります。引数なしの lsof は開いているものすべてを出力して膨大になるため、実務では必ず目的を絞って使います。出力には、COMMAND(プロセス名)、PID(プロセス番号)、USER(所有者)、FD(ファイルディスクリプタ番号と種別)、TYPE(種類)、NAME(対象のパスや接続先)などが並び、「どのプロセスが、何を、どんな形で開いているか」が読み取れます。

よく使う絞り込みを覚えておくと実用的です。lsof /var/log/messages のようにファイルを指定すると、そのファイルを開いているプロセスが分かります。これは前述のディスク調査で「削除したのに容量が戻らない」ときに、ファイルを掴んでいる犯人を探すのに役立ちます。lsof -u user01 とすればそのユーザが開いているものすべて、lsof -p 1234 とすれば特定のPIDが開いているものすべてを一覧できます。あるディレクトリ配下のファイルが「使用中で削除・アンマウントできない」ときは、lsof +D /mnt/data のようにすると、その配下を掴んでいるプロセスを突き止められます。

ネットワーク接続も lsof で見る

ソケットもファイルとして扱われるので、ネットワーク接続も lsof で調べられます。lsof -i とすると、開いているすべてのネットワーク接続(待ち受け中・通信中の両方)が一覧でき、どのプロセスがどのポートを使っているかが分かります。lsof -i :80 のようにポート番号を指定すれば、80番ポートを使っているプロセスだけに絞れます。「このポートを使っているのは誰だ」を調べるのに直感的で、たとえば新しいサービスを起動しようとして『ポートが既に使われています(Address already in use)』と言われたとき、lsof -i :8080 でそのポートを先に掴んでいるプロセスを特定できます。

ファイルディスクリプタの上限と「Too many open files」

ファイルディスクリプタにまつわる、実務で頻出のトラブルがあります。Linuxでは、1つのプロセスが同時に開けるファイル(=ファイルディスクリプタ)の数に上限が設けられています。これは暴走したプログラムが資源を無限に食い潰すのを防ぐための安全装置ですが、多数の接続を捌くWebサーバやデータベースでは、この上限に達してしまうことがあります。上限を超えてさらに開こうとすると、「Too many open files(開きすぎです)」というエラーが出て、新しい接続やファイルアクセスが失敗します。アクセスが増えた途端にサーバがエラーを返し始めたら、この上限到達を疑います。

調査では、まず ulimit -n で現在のプロセスが開けるファイル数の上限(ソフトリミット)を確認します。そのうえで、問題のプロセスが実際にいくつ開いているかを lsof -p PID | wc -l で数え、上限に近づいていないかを見ます。上限に達しているなら、対処は2方向です。1つは、本当にそれだけの接続が必要なら上限を引き上げること。これはサービスごとの設定(systemd の LimitNOFILE など)や、システム全体の設定で行います。もう1つは、そもそも開いたファイルや接続をきちんと閉じていないプログラム側のバグ(ファイルディスクリプタの「リーク」)を疑い、コードを修正することです。エラーが時間とともにじわじわ増えていく場合は、後者のリークの可能性が高くなります。

ss はソケット専用の高速ツール

lsof は何でも調べられる万能選手ですが、ネットワークのソケットだけを手早く確認したいなら、専用ツールの ss のほうが高速で軽快です。ss は socket statistics の略で、待ち受けポートや確立中の接続を瞬時に一覧します。前のトピックでも触れたとおり、ss -tlnp(TCPの待ち受けポートをプロセス付きで表示)が代表的な使い方です。これに加えて、確立済みの接続まで含めて全体を見たいときは ss -tanp のように -a(待ち受けと確立の両方)を使います。ss は出力をオプションで細かく絞れるのも利点で、たとえば ss -t state established で確立中のTCP接続だけを抜き出す、といった調査もできます。大量の接続があるサーバでは、lsof より ss のほうが結果がすぐ返るため、ネットワークまわりの第一手として重宝します。

実務での使いどころ

使い分けの目安は、ネットワークのソケットだけを素早く見たいなら ss、ファイル・ソケットを横断して「誰が何を開いているか」を幅広く調べたいなら lsof、です。具体的には、待ち受けポートの確認は ss -tlnp、ポートを掴んでいるプロセスの特定は lsof -i :ポート、削除済みファイルや使用中ディレクトリの調査は lsof、「Too many open files」エラーの調査は ulimit -n と lsof -p PID | wc -l の組み合わせ、というように引き出しを持っておくと、ファイルディスクリプタ起因の障害に素早く対応できます。「すべてはファイル」という発想を軸に、lsof と ss を使い分けられるようになると、一見ばらばらに見えるファイル・プロセス・ネットワークの問題を、ひとつながりの視点で調べられるようになります。

この項目に出てくる用語

ファイルディスクリプタふぁいるでぃすくりぷた
プロセスが開いているファイルやソケットを指す番号。上限がある。
ポートぽーと
通信の宛先を区別する番号。サービスは特定ポートで待ち受ける。

関連コマンド

lsofss

▶ 学習アプリでこの続きを学ぶ・演習する