【Linux】lsofで開いているファイルを調べる方法|ポート占有プロセス特定・削除済みファイルの発見

【Linux】lsofで開いているファイルを調べる方法|ポート占有プロセス特定・削除済みファイルの発見 Linux

lsoflist open files)は、その名の通り「今、開かれているファイル」を一覧するコマンドです。Linuxでは「すべてはファイル」という思想があり、通常のファイルだけでなくネットワーク接続(ポート)・ディレクトリ・デバイスなども「開いているファイル」として扱われます。そのためlsofは、「このポートは誰が使っている?」「このファイルはどのプロセスが掴んでいる?」といった調査に絶大な力を発揮します。

特にlsofが真価を発揮するのが、他のコマンドでは解決しにくい2つの謎——「ポートが使用中で起動できない」ssの回で触れた問題)と「ファイルを削除したのにディスク容量が減らない」——の原因究明です。この記事では、実機のLinux(WSLのDebian)で実際にこれらの状況を再現しながら、lsofの使い方を整理します。

先に結論

  • lsof -i :ポート番号で、そのポートを使っているプロセスを特定できます。
  • lsof -p PIDで、特定プロセスが開いているファイルを一覧します。
  • lsof ファイル名で、そのファイルを開いているプロセスが分かります。
  • lsof | grep deletedで、削除済みなのに開かれたままのファイルを発見できます。
  • lsof -u ユーザーで特定ユーザー、lsof -tPIDだけを出力します。
  • lsof -t -i :ポート | xargs killで、ポート占有プロセスを終了できます。

ポートの一覧はss・netstat、ディスク容量の謎はdu・df、プロセスの終了はps・killもあわせて参考になります。

スポンサーリンク

【定番】ポートを使っているプロセスを特定する

lsofの最も有名な使い方がlsof -i :ポート番号です。「ポートが既に使われている(Address already in use)」というエラーのとき、そのポートを掴んでいるプロセスを一発で特定できます。

lsof -i :ポート
# 18080番ポートを使っているプロセスを調べる
lsof -i :18080
# COMMAND PID USER  FD  TYPE DEVICE SIZE/OFF NODE NAME
# nc       22 root   3u IPv4  11315     0t0  TCP localhost:18080 (LISTEN)
#   ↑コマンド  ↑PID          ↑ポートと状態

# 特定のプロトコルに絞る
lsof -i tcp:80        # TCP の80番
lsof -i udp:53        # UDP の53番

# すべてのネットワーク接続を見る
lsof -i

実機で、ポート18080を開いてからlsof -i :18080を実行したところ、ncというコマンド(PID 22)がそのポートをLISTENしていることが一目で分かりました。ssでもポートとプロセスは調べられますが、lsof -iより読みやすく、ファイル・ネットワークを横断的に調べられるのが強みです。「開発サーバーを起動しようとしたら3000番が使用中と言われた」というとき、lsof -i :3000で犯人を特定できます。

プロセス・ファイルから調べる(-p / ファイル指定)

逆方向の調査もできます。lsof -p PIDで「あるプロセスが何を開いているか」lsof ファイル名で「あるファイルを誰が開いているか」を調べられます。

-p とファイル指定
# 特定プロセス(PID)が開いているファイルを一覧
lsof -p 1234
#   ↑ そのプロセスが使うファイル・ライブラリ・ソケットが全部見える

# 特定のファイルを、今どのプロセスが開いているか
lsof /var/log/app.log
# COMMAND PID USER  FD TYPE ... NAME
# app     567 root  3w REG  ... /var/log/app.log

# ディレクトリを開いているプロセス(アンマウントできない原因調査)
lsof /mnt/usb

実機でも、lsof -p PIDそのプロセスが開いている全ファイル(実行ファイル本体・ライブラリ・カレントディレクトリ・ネットワークソケットなど)が一覧でき、lsof /etc/hostnameそのファイルを開いているプロセスが特定できることを確認しました。後者は特に、「USBメモリをアンマウントできない(Device is busy)」というときに役立ちます。lsof /mnt/usbそのディレクトリを掴んでいるプロセスを見つけ、終了させればアンマウントできます。FD列のrは読み込み、wは書き込み、uは読み書き両用を表します。

【最重要】削除済みだが開いたままのファイルを発見する

lsofが最も輝く場面がこれです。du・dfの記事で触れた「ファイルを削除したのにディスク容量が減らない」という謎——その原因である「削除済みだが、まだプロセスが開いたままのファイル」を、lsofで特定できます。

削除済みファイルの発見(実証)
# 削除されたのに開かれたままのファイルを探す
lsof | grep deleted
# bash 19 root 9r REG 8,48 20971520 14515 /tmp/bigdel (deleted)
#                        ↑まだ20MB占有  ↑ファイル名 (deleted)

# → このファイルは rm 済みだが、PID 19 が開いているため
#   ディスク容量が解放されていない

# 対処: そのプロセス(PID 19)を再起動または終了する
kill 19    # または該当サービスを restart
「消したのに容量が減らない」の犯人を特定できる(実証)

実機で、20MBのファイルを作成し、プロセスが開いたままrmで削除してからlsof | grep deletedを実行しました。すると、/tmp/lsd/bigdel (deleted)という「削除済み」の表示とともに、まだ20971520バイト(=20MB)を占有していることが、開いているプロセス(PID)付きで判明しました。du・dfの記事で説明したとおり、Linuxではファイルをrmしても、それを開いているプロセスが残っている限り、実際のディスク領域は解放されませんlsduには見えないのにdfの使用量が減らない——この不可解な状況の正体を暴くのがlsof | grep deletedです。よくあるのが、ログファイルをrmしたのに、それを書き続けているWebサーバーやアプリが開いたままで、容量が全く減らないケースです。対処は、そのファイルを開いているプロセスを再起動(または終了)すること。プロセスが閉じた瞬間、ディスク領域が解放されます。「ディスクが満杯なのに大きなファイルが見当たらない」ときの最終手段が、このlsof | grep deletedです。

-tでPIDだけ出力してkillと連携

lsof -tは、PIDだけを出力するオプションです。これをxargskillと組み合わせると、「ポートを使っているプロセスを特定して終了する」を1行で実行できます。

-t とkillの連携
# -t: PIDだけを出力
lsof -t -i :18080
# 22        ← PID だけがシンプルに返る

# ポートを掴んでいるプロセスを特定して即終了(実務の定番)
kill $(lsof -t -i :3000)
#   ↑ 3000番を使っているプロセスを kill

# xargs を使う書き方(複数PIDにも対応)
lsof -t -i :3000 | xargs kill

# ファイルを開いているプロセスを全部終了
lsof -t /path/to/file | xargs kill

実機でも、lsof -t -i :18081PID(43)だけをシンプルに返すことを確認しました。通常のlsof出力は見出しや詳細情報が多いですが、-tを付けるとPIDのみになるため、killxargsにそのまま渡せます。kill $(lsof -t -i :3000)は、開発中に「ポートが解放されない」ときの定番の対処コマンドです。ただし他の重要なプロセスを巻き込まないよう、実行前にlsof -i :3000で対象を確認してから使うのが安全です。

主な書き方一覧

lsofでよく使う書き方をまとめます。

書き方 働き
lsof -i :ポート ポートを使うプロセスを特定
lsof -p PID プロセスが開くファイルを一覧
lsof ファイル ファイルを開くプロセスを特定
lsof | grep deleted 削除済みだが開かれたファイル
lsof -u ユーザー 特定ユーザーが開くファイル
lsof -t PIDだけ出力(kill連携)

よくある失敗

出力が多すぎて見づらい

-i :ポート-p PID| grepで絞り込みます。

他人のプロセスが表示されない

すべてを見るにはroot権限が必要です。sudo lsofを使います。

削除したのに容量が減らない原因が分からない

lsof | grep deletedで、開いたままの削除済みファイルを探します。

lsof -t killで重要プロセスまで終了する

実行前にlsof -i :ポートで対象を確認します。

アンマウントできない(Device is busy)

lsof マウントポイントで、掴んでいるプロセスを特定します。

よくある質問

Qポートを使っているプロセスを調べるには?
Alsof -i :ポート番号を使います。たとえばlsof -i :3000で、3000番ポートを使っているプロセスの名前とPIDが分かります。実機でも、開いたポートのプロセスが正しく特定できることを確認しています。PIDだけ欲しいならlsof -t -i :3000で、kill $(lsof -t -i :3000)とすれば終了までできます。
Qファイルを削除したのにディスク容量が減りません。
Aそのファイルを開いたままのプロセスがある可能性が高いです。lsof | grep deletedを実行すると、削除済みなのに開かれているファイルと、そのプロセス・占有サイズが表示されます。実機でも、rm済みの20MBファイルが(deleted)として容量を占有し続けているのを検出できました。該当プロセスを再起動すれば領域が解放されます。
QアンマウントしようとするとDevice is busyになります。
Aそのディレクトリ(マウントポイント)を開いているプロセスがあるためです。lsof マウントポイント(例: lsof /mnt/usb)で、掴んでいるプロセスを特定できます。そのプロセスを終了するか、カレントディレクトリがそこにあるシェルを移動させれば、アンマウントできるようになります。
Q特定のプロセスが何を開いているか調べるには?
Alsof -p PIDを使います。そのプロセスが開いているファイル・ライブラリ・ネットワークソケットなどがすべて一覧表示されます。プロセスがどのファイルにアクセスしているかを調べたいときや、ファイルディスクリプタのリークを調査したいときに便利です。
Qlsofで他のユーザーのプロセスが見えません。
Aすべてのプロセスの開いているファイルを見るには、root権限が必要です。sudo lsofのようにsudoを付けて実行してください。一般ユーザーのままでは、自分のプロセスが開いているファイルしか表示されません。

まとめ

  • lsof -i :ポートでポート占有プロセスを特定(起動できないとき)。
  • lsof -p PIDlsof ファイルで、双方向に調査できます。
  • lsof | grep deletedで「消したのに容量が減らない」原因を発見。
  • lsof -tでPIDだけ出力、kill $(lsof -t -i :ポート)で終了。
  • すべてを見るにはsudo、アンマウント不可もlsofで調査。

lsofは、「すべてはファイル」というLinuxの思想を体現した、強力な調査ツールです。ポートの謎、ディスクの謎、アンマウントの謎——多くの「なぜ?」をlsofが解き明かします。ssdu・dfと組み合わせれば、サーバートラブルの原因究明が格段に速くなります。

シリーズで学ぶLinuxコマンド基礎