lsof(list open files)は、その名の通り「今、開かれているファイル」を一覧するコマンドです。Linuxでは「すべてはファイル」という思想があり、通常のファイルだけでなくネットワーク接続(ポート)・ディレクトリ・デバイスなども「開いているファイル」として扱われます。そのためlsofは、「このポートは誰が使っている?」「このファイルはどのプロセスが掴んでいる?」といった調査に絶大な力を発揮します。
特にlsofが真価を発揮するのが、他のコマンドでは解決しにくい2つの謎——「ポートが使用中で起動できない」(ssの回で触れた問題)と「ファイルを削除したのにディスク容量が減らない」——の原因究明です。この記事では、実機のLinux(WSLのDebian)で実際にこれらの状況を再現しながら、lsofの使い方を整理します。
lsof -i :ポート番号で、そのポートを使っているプロセスを特定できます。lsof -p PIDで、特定プロセスが開いているファイルを一覧します。lsof ファイル名で、そのファイルを開いているプロセスが分かります。lsof | grep deletedで、削除済みなのに開かれたままのファイルを発見できます。lsof -u ユーザーで特定ユーザー、lsof -tでPIDだけを出力します。lsof -t -i :ポート | xargs killで、ポート占有プロセスを終了できます。
ポートの一覧はss・netstat、ディスク容量の謎はdu・df、プロセスの終了はps・killもあわせて参考になります。
【定番】ポートを使っているプロセスを特定する
lsofの最も有名な使い方がlsof -i :ポート番号です。「ポートが既に使われている(Address already in use)」というエラーのとき、そのポートを掴んでいるプロセスを一発で特定できます。
# 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 ファイル名で「あるファイルを誰が開いているか」を調べられます。
# 特定プロセス(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しても、それを開いているプロセスが残っている限り、実際のディスク領域は解放されません。lsやduには見えないのにdfの使用量が減らない——この不可解な状況の正体を暴くのがlsof | grep deletedです。よくあるのが、ログファイルをrmしたのに、それを書き続けているWebサーバーやアプリが開いたままで、容量が全く減らないケースです。対処は、そのファイルを開いているプロセスを再起動(または終了)すること。プロセスが閉じた瞬間、ディスク領域が解放されます。「ディスクが満杯なのに大きなファイルが見当たらない」ときの最終手段が、このlsof | grep deletedです。
-tでPIDだけ出力してkillと連携
lsof -tは、PIDだけを出力するオプションです。これをxargsやkillと組み合わせると、「ポートを使っているプロセスを特定して終了する」を1行で実行できます。
# -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 :18081がPID(43)だけをシンプルに返すことを確認しました。通常のlsof出力は見出しや詳細情報が多いですが、-tを付けるとPIDのみになるため、killやxargsにそのまま渡せます。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 マウントポイントで、掴んでいるプロセスを特定します。
よくある質問
lsof -i :ポート番号を使います。たとえばlsof -i :3000で、3000番ポートを使っているプロセスの名前とPIDが分かります。実機でも、開いたポートのプロセスが正しく特定できることを確認しています。PIDだけ欲しいならlsof -t -i :3000で、kill $(lsof -t -i :3000)とすれば終了までできます。lsof | grep deletedを実行すると、削除済みなのに開かれているファイルと、そのプロセス・占有サイズが表示されます。実機でも、rm済みの20MBファイルが(deleted)として容量を占有し続けているのを検出できました。該当プロセスを再起動すれば領域が解放されます。lsof マウントポイント(例: lsof /mnt/usb)で、掴んでいるプロセスを特定できます。そのプロセスを終了するか、カレントディレクトリがそこにあるシェルを移動させれば、アンマウントできるようになります。lsof -p PIDを使います。そのプロセスが開いているファイル・ライブラリ・ネットワークソケットなどがすべて一覧表示されます。プロセスがどのファイルにアクセスしているかを調べたいときや、ファイルディスクリプタのリークを調査したいときに便利です。sudo lsofのようにsudoを付けて実行してください。一般ユーザーのままでは、自分のプロセスが開いているファイルしか表示されません。まとめ
lsof -i :ポートでポート占有プロセスを特定(起動できないとき)。lsof -p PID・lsof ファイルで、双方向に調査できます。lsof | grep deletedで「消したのに容量が減らない」原因を発見。lsof -tでPIDだけ出力、kill $(lsof -t -i :ポート)で終了。- すべてを見るにはsudo、アンマウント不可も
lsofで調査。
lsofは、「すべてはファイル」というLinuxの思想を体現した、強力な調査ツールです。ポートの謎、ディスクの謎、アンマウントの謎——多くの「なぜ?」をlsofが解き明かします。ssやdu・dfと組み合わせれば、サーバートラブルの原因究明が格段に速くなります。
- grep(文字列検索)
- find(ファイル検索)
- sed(置換・行編集)
- awk(列抽出・集計)
- cut(列の切り出し)
- chmod(パーミッション)
- tar(圧縮・解凍)
- gzip・gunzip(ファイル圧縮)
- リダイレクトとパイプ
- echo・printf(文字列出力)
- ps・kill(プロセス管理)
- free・uptime(メモリ/負荷)
- top(リアルタイム監視)
- watch(定期実行監視)
- 環境変数とPATH
- which・type(コマンドの正体)
- ln(シンボリックリンク)
- cp・mv・rm(コピー/移動/削除)
- touch・mkdir(ファイル/フォルダ作成)
- basename・dirname(パス分解)
- history(コマンド履歴)
- curl(HTTP通信・API)
- wget(ダウンロード)
- ping(疎通確認)
- dig・nslookup(DNS調査)
- ss・netstat(ポート確認)
- lsof(開いているファイル調査)
- jq(JSON処理)
- vim(基本操作・終了方法)
- cron・crontab(定期実行)
- test・[ ](条件判定)
- read(入力の読み取り)
- date(日付・時刻)
- sort・uniq・wc(並べ替え/集計)
- xargs(一括処理)
- chown・chgrp(所有者/グループ変更)
- sudo(管理者権限)
- diff(ファイル比較)
- du・df(ディスク使用量)
- head・tail(先頭/末尾・ログ監視)
- cat・less(ファイル表示)
- alias(コマンドの別名)
- nohup(SSH切断対策)
- tmux(セッション管理)
- よく使うコマンドまとめ
- cd(ディレクトリ移動)
