lsof 入門 - 開いているファイルとポートを調べる

lsof 入門 - 開いているファイルとポートを調べる

この記事で解決できること

  • lsofどのプロセスがどのファイル・ポートを開いているか を特定できる
  • device is busy でアンマウントできない」「ポートが既に使われている」を即切り分けできる
  • 削除したのに ディスクが空かない 原因(deleted ファイル)を見つけられる

結論(実務の型)

  • ポート調査lsof -i :8080
  • プロセスが開くファイルlsof -p <PID>
  • ファイルを掴む犯人lsof /path/to/file
  • 出力が空・遅いときは sudo-n -P を足す

前提(対象環境)

  • OS:Ubuntu / RHEL 系(lsof は別パッケージのことがある)
  • 未導入なら sudo apt install lsof / sudo dnf install lsof
  • 他ユーザーのプロセスまで見るには sudo が必要

lsof とは何か?

結論: lsof(list open files)は「いま開かれているファイル」を一覧するコマンド。Linux ではソケットやパイプもファイル扱いなので、ネットワーク調査にも使える。

Linux では ほぼすべてがファイル として扱われる。通常ファイルやディレクトリだけでなく、ネットワークソケット・パイプ・デバイス・ブロックデバイスまで「開いているファイル」に含まれる。lsof はこれらを横断的に一覧できるため、トラブル調査の万能ツールになる。

引数なしで実行すると、システム全体の開いているファイルが大量に表示される。

$ sudo lsof | head
COMMAND     PID   USER   FD   TYPE DEVICE  SIZE/OFF    NODE NAME
systemd       1   root  cwd    DIR  254,1      4096       2 /
systemd       1   root  txt    REG  254,1   1620224  393431 /usr/lib/systemd/systemd
sshd        812   root    3u  IPv4  18654       0t0     TCP *:ssh (LISTEN)

各列の意味は次のとおり。

  • COMMAND / PID / USER:開いているプロセスとその所有者
  • FD:ファイルディスクリプタ番号(cwd=カレントディレクトリ、txt=実行ファイル、3u=fd3 を読み書きで開いている等)
  • TYPEREG(通常ファイル)/ DIR / IPv4 / unix(UNIX ソケット)など
  • NAME:ファイルパスや接続先

引数なしの全件出力は実務では使わない。次章以降の 絞り込み が本番。

ポートを使っているプロセスは?

結論: lsof -i :ポート番号 で、そのポートを開いているプロセスを PID 付きで特定できる。Address already in use の犯人探しの定番。

最も使う場面が「ポートの占有調査」。-i はネットワーク接続に絞り込むオプション。

# 8080 番ポートを使っているプロセス
$ sudo lsof -i :8080
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node    24531 hide   22u  IPv4 184213      0t0  TCP *:8080 (LISTEN)

PID(この例では 24531)が分かれば、そのまま停止できる。

$ kill 24531

LISTEN 中のポートだけを一覧したいときは、プロトコルと状態で絞り込む。

# TCP で待ち受け中のポートをすべて表示
$ sudo lsof -iTCP -sTCP:LISTEN -P -n
  • -P:ポート番号を http などの名前に変換しない(数字のまま)
  • -n:IP アドレスを DNS で名前解決しない

-P -n を付けると名前解決を省略でき、出力が速く・読みやすくなる。調査では基本セット。

特定のホストやポートだけを見ることもできる。

$ sudo lsof -i TCP:22          # 22番(SSH)関連の接続
$ sudo lsof -i @192.168.1.10   # 特定ホストとの接続

プロセスが開いているファイルを見るには?

結論: lsof -p <PID> でそのプロセスが開いている全ファイル(ログ・ソケット・ライブラリ)を一覧できる。挙動が読めないプロセスの調査に有効。

# PID 24531 が開いているファイル
$ sudo lsof -p 24531

ログファイルが書き込まれている場所、読み込んでいる設定ファイル、接続中のソケットがまとめて分かる。複数 PID はカンマ区切りで指定する。

$ sudo lsof -p 24531,800

ユーザー単位・コマンド名単位での絞り込みも可能。

$ sudo lsof -u hide        # ユーザー hide が開いているファイル
$ sudo lsof -c nginx       # コマンド名 nginx で始まるプロセス

-u-c-i を同時に指定すると OR 条件(いずれかに合致)になる。AND で絞りたい場合は -a を加える。

# nginx かつ TCP 接続のみ(AND)
$ sudo lsof -a -c nginx -i TCP

このファイルを掴んでいるのは誰?

結論: lsof /path で、指定ファイル(やディレクトリ)を開いているプロセスを逆引きできる。device is busy でアンマウントできないときの切り札。

USB やネットワークドライブをアンマウントしようとして target is busy と怒られた経験は多いはず。原因は「そのディレクトリ配下のファイルを誰かが開いている」こと。

# /mnt/usb を掴んでいるプロセスを探す
$ sudo lsof /mnt/usb

ディレクトリ配下を再帰的に調べるには +D を使う。

$ sudo lsof +D /mnt/usb

犯人の PID が分かったら、プロセスを終了するかカレントディレクトリを移動してもらえばアンマウントできる。

kill と組み合わせる型

-t は PID だけを出力するオプション。kill にそのまま渡せる。

# /mnt/usb を掴むプロセスをすべて終了
$ sudo kill $(sudo lsof -t /mnt/usb)

強制終了は最終手段。まずは何のプロセスか -t なしで確認すること。

削除したのにディスクが空かない

結論: プロセスが開いたままのファイルを削除しても、プロセスが終了するまで領域は解放されない。lsof | grep deleted で掴んでいるプロセスを特定する。

「巨大なログを rm したのに df の空き容量が増えない」——典型的な落とし穴。ファイルを開いているプロセスがある間は、rm してもリンクが消えるだけで実体(inode)は残り続ける。

# 削除済みなのに開かれ続けているファイルを探す
$ sudo lsof -nP | grep '(deleted)'
java   3120 app   5w   REG  254,1  2147483648  394102 /var/log/app/huge.log (deleted)

この場合、領域を解放するには プロセスを再起動(または該当 fd を閉じる)必要がある。huge.logrm しただけでは不十分だと分かる。

サービスのログファイルは rm ではなく、ローテーション(logrotatecopytruncate 等)か truncate -s 0 で空にするのが安全。rm は deleted 状態を生みやすい。

よく使うオプション早見表

結論: 調査の起点は -i(ポート)・-p(プロセス)・パス指定(ファイル)の 3 つ。あとは -n -P で高速化、-t で kill 連携。

やりたいこと コマンド
ポート占有を調べる lsof -i :8080
LISTEN 中のポート一覧 lsof -iTCP -sTCP:LISTEN -P -n
プロセスの開くファイル lsof -p <PID>
ユーザーの開くファイル lsof -u <user>
ファイルを掴むプロセス lsof /path/to/file
ディレクトリ配下を再帰調査 lsof +D /path
削除済みで開かれたファイル lsof -nP | grep '(deleted)'
PID のみ出力(kill 連携) lsof -t /path

コピペ用:調査テンプレ

# ポートの占有犯を探す
sudo lsof -i :8080 -P -n

# device is busy の犯人を探す
sudo lsof +D /mnt/usb

# 削除済みで容量を食っているファイル
sudo lsof -nP | grep '(deleted)'

次に読む