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 を読み書きで開いている等)TYPE:REG(通常ファイル)/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.log を rm しただけでは不十分だと分かる。
サービスのログファイルは rm ではなく、ローテーション(logrotate の copytruncate 等)か 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)'