Linux lsof 完全ガイド - ポート競合から削除済みファイルの容量解放まで実務で役立つ重要Tips

概要

Linux システムの運用中に発生する「ポートの競合」や「ファイルを削除しても減らないディスク容量」といった問題は、lsof コマンドを使用すれば即座に解決できます。本記事では、すべてのリソースをファイルとして管理する Linux 環境において、lsof を実務にすぐ適用できる重要テクニックを紹介します。ポートの追跡からファイルロックの解除まで、システムエンジニアに必須のトラブルシューティングのノウハウをステップバイステップで解説します。

lsof の基本確認および特定ユーザー/プロセスのオープンファイル確認

システムに lsof コマンドがインストールされているか確認し、インストールされていない場合はパッケージをインストールするために command -v lsof >/dev/null 2>&1 || (apt-get update -qq && apt-get install -y lsof) コマンドを実行します。

command -v lsof >/dev/null 2>&1 || (apt-get update -qq && apt-get install -y lsof)

lsof コマンドのインストールバージョンとビルド情報を確認するために lsof -v コマンドを実行します。
⚙️ [主要オプション]

-u : 特定のユーザーアカウントが開いているファイルおよびプロセス一覧を確認します。
-c : 指定したプロセス名で始まるプロセスが開いているファイル一覧をフィルタリングします。
-p : 特定のプロセス ID (PID) が開いているファイル一覧を確認します。
-i : ネットワークソケットおよび特定ポートを使用しているプロセスを確認します。
+D : 指定したディレクトリおよび配下のパスで開かれているファイル一覧を再帰的に検索します。
-t : プロセス ID (PID) のみを1行ずつ簡潔に出力するため、スクリプトとの連携に便利です。

lsof -v

lsof の検証用テストディレクトリとサンプルファイルを準備するために mkdir -p /tmp/lsof_lab && echo '테스트 파일 내용' > /tmp/lsof_lab/sample.txt コマンドを実行します。

mkdir -p /tmp/lsof_lab && echo ‘테스트 파일 내용’ > /tmp/lsof_lab/sample.txt

作成したサンプルファイルをプロセスが開き続ける状態にするため、バックグラウンドで追跡を行う tail -f /tmp/lsof_lab/sample.txt & コマンドを実行します。

tail -f /tmp/lsof_lab/sample.txt &

lsof -u $(whoami) | head -n 15 コマンドは、現在ログインしているユーザーが実行中のプロセスによって占有されているファイル一覧を上位15行まで表示します。
基本的なシステムライブラリや実行ファイルなど、現在のアカウントが開いているファイルの詳細情報を確認できます。

lsof -u $(whoami) | head -n 15

lsof -c tail コマンドは、プロセス名が tail であるプロセスが開いているファイルやライブラリの一覧を検索して出力します。
これにより、バックグラウンドで実行した tail コマンドがどのファイルディスクリプタや共有ライブラリを参照しているかを確認できます。

lsof -c tail

検証終了後、バックグラウンドで実行されていた tail プロセスを安全に終了・整理するために killall tail 2>/dev/null || true コマンドを実行します。

killall tail 2>/dev/null || true

ネットワークポートの確認とプロセス競合のトラブルシューティング

ポート確認およびプロセス競合の検証環境を整えるため、システムに python3 がインストールされているか確認し、未インストールの場合はパッケージをインストールします。

command -v python3 >/dev/null 2>&1 || (apt-get update -qq && apt-get install -y python3)

ネットワークポート占有のテストのため、8080番ポートでシンプルな Web サーバーをバックグラウンドで起動します。

python3 -m http.server 8080 >/dev/null 2>&1 &

バックグラウンドで起動した Web サーバープロセスが8080番ポートに正常にバインドされるまで1秒間待機します。

sleep 1

lsof -i :8080 コマンドは、8080番ポートを使用しているプロセスを確認します。
出力結果から、PID 371 の python3 プロセスが8080番ポートで LISTEN 状態で待機していることが確認できます。

lsof -i :8080

lsof -i -P -n | head -n 15 コマンドは、システムのネットワークソケット一覧をポート番号や IP アドレスの変換を行わず、数値のまますばやく出力します。
DNS 逆引きやサービスポート名への名前解決処理を省略するため、遅延なく迅速にポート占有状況を把握できます。

lsof -i -P -n | head -n 15

lsof -i TCP:8080 -sTCP:LISTEN コマンドは、8080番ポートの中でも TCP プロトコルかつ LISTEN 状態にある接続のみをピンポイントでフィルタリングして出力します。
不要なセッション接続を除外し、実際に該当ポートで接続待機中のデーモンプロセスのみを正確に特定したい場合に役立ちます。

lsof -i TCP:8080 -sTCP:LISTEN

検証終了後、8080番 TCP ポートを占有していたバックグラウンド Web サーバープロセスを強制終了し、占有リソースを整理します。

fuser -k 8080/tcp 2>/dev/null || kill $(lsof -t -i :8080) 2>/dev/null || true

特定ディレクトリおよびアンマウントを妨げるファイル (Device Busy) の追跡

ディレクトリの占有およびアンマウント妨害の状況を再現するため、検証用ディレクトリを作成して該当パスに移動します。

mkdir -p /tmp/mount_test && cd /tmp/mount_test

プロセスが開く対象となるログファイルを作成するため、echo '작업 중인 파일' > active_work.log コマンドを実行します。

echo ‘작업 중인 파일’ > active_work.log

作成したファイルを標準入力として参照し、継続的に占有し続けるようバックグラウンドで sleep プロセスを実行します。

sleep 30 < active_work.log &

占有中のディレクトリの外部から状態を確認するため、ホームディレクトリへ作業パスを変更します。

cd /root || cd ~

lsof +D /tmp/mount_test コマンドは、指定したディレクトリおよびその配下のパスで開かれているすべてのファイルとプロセスを再帰的に追跡して出力します。
出力結果から、PID 450 の sleep プロセスが該当ディレクトリをカレントワーキングディレクトリ (cwd) として参照し、さらに active_work.log ファイルを読み取りモード (0r) で開いているため、アンマウントを妨げる原因になっていることが確認できます。

lsof +D /tmp/mount_test

検証終了後、ディレクトリとファイルを占有していたバックグラウンドの sleep プロセスを安全に終了します。

killall sleep 2>/dev/null || true

検証に使用した一時テストディレクトリと配下のファイルをすべて削除し、システムリソースを整理します。

rm -rf /tmp/mount_test

削除されてもディスクを占有し続けるゴーストファイル (deleted) の復元と解放

ディスク容量のリーク検証のため、実習用ディレクトリを作成し、10MB サイズの大きなテストファイルを生成します。

mkdir -p /tmp/leak_test && dd if=/dev/zero of=/tmp/leak_test/large.img bs=1M count=10 >/dev/null 2>&1

作成した大容量ファイルのファイルハンドルをプロセスが保持し続けるよう、バックグラウンドで追跡を行います。

tail -f /tmp/leak_test/large.img &

占有中の大容量ファイルをファイルシステム上から強制的に削除し、ゴーストファイルによる容量リークの状況を再現します。

rm -f /tmp/leak_test/large.img

lsof | grep '(deleted)' | head -n 5 コマンドは、ファイルシステム上からは削除されたものの、プロセスが開き続けているためディスク容量を占有しているファイル一覧を確認します。
これにより、rm コマンドで削除したにもかかわらずディスク領域が解放されないゴーストファイルと、該当のプロセスを迅速に追跡できます。

lsof | grep ‘(deleted)’ | head -n 5

lsof -t で抽出したプロセス ID をもとに、/proc/$TARGET_PID/fd/ ディレクトリのファイルディスクリプタ一覧を確認します。
プロセスが参照しているファイルディスクリプタ番号を直接確認することで、プロセスを再起動せずに容量を空けたり、必要に応じて該当ディスクリプタ経由で削除された元のデータを復元したりできます。

TARGET_PID=$(lsof -t /tmp/leak_test/large.img 2>/dev/null | head -n 1) && [ -n “$TARGET_PID” ] && ls -l /proc/$TARGET_PID/fd/ || true

検証終了後、ゴーストファイルを占有し続けていたバックグラウンドプロセスを安全に終了し、ディスク容量を完全に解放します。

killall tail 2>/dev/null || true

検証に使用した一時テストディレクトリを完全に削除し、システムリソースを整理します。

rm -rf /tmp/leak_test

ここまで、lsof コマンドを活用したポート競合の解消から、削除済みファイルのディスク容量解放まで、実務における重要 Tips を確認しました。
本記事で解説した内容が、実際のサーバー運用やトラブルシューティングにおける問題解決の一助となれば幸いです。