「device is busy」でアンマウントできない時の対処
「device is busy」とは何が起きているのか?
結論: アンマウント対象のファイルシステムを、まだ誰か(プロセス・別マウント・swap 等)が使っている状態。カーネルが
EBUSYを返して umount を拒否している。外す前に「何が掴んでいるか」を特定するのが先決。
umount が次のように弾かれる典型。
umount: /mnt/data: target is busy.
古いディストリや一部ツールでは同じ状態が device is busy / device or resource busy(errno の EBUSY)として現れる。メッセージは違っても原因は同じで、対象を参照しているものが残っている。
掴んでいる主体は大きく次の系統に分かれる。切り分けの優先順位もこの順。
- A. プロセスがファイルを開いている(最頻)— マウント配下のファイルを開いたまま / 実行中バイナリ / ログ書き込み中
- B. カレントディレクトリがマウント内— シェルや常駐プロセスの cwd が
/mnt/data配下にある - C. マウントが入れ子— その上に bind マウントや overlay が重なっている
- D. swap / loop など別用途で使用中— 対象デバイスを swap や loop デバイスとして使っている
device is busy と Read-only file system は別物。前者は「使用中で外せない」、後者は「書き込み禁止状態」。エラー文を取り違えると対処を誤る。read-only については 「Read-only file system」の対処 を参照。
誰が掴んでいるかを特定するには?
結論: まず
fuser -vm <マウントポイント>で「そのファイルシステムを使う全プロセス」を一覧する。ACCESS列で開いているファイル(f)・カレントディレクトリ(c)・実行中(e)・mmap(m) を区別できる。補完としてlsofを使う。
fuser でマウント単位に洗い出す
-m はマウントポイント(またはブロックデバイス)を指定し、そのファイルシステムを利用する全プロセスを返す。-v で詳細表示。
fuser -vm /mnt/data
USER PID ACCESS COMMAND
/mnt/data: root kernel mount /mnt/data
alice 2314 ..c.. bash
alice 2890 F.... tail
ACCESS 列の意味を読む。これが「なぜ busy か」の直接の答えになる。
c… そのプロセスの カレントディレクトリ がマウント配下(→ B のパターン)e… マウント配下のバイナリを 実行中f… ファイルを オープン中(大文字Fは書き込みオープン)r… ルートディレクトリとして使用m… ファイルを mmap(共有ライブラリ等)
上の例なら、bash(cwd が中)と tail(ファイルを開いている)が原因。
lsof で個別ファイルまで追う
どのファイルを掴んでいるか具体的に知りたいときは lsof。マウントポイント配下を再帰的に見るなら +D、デバイス単位なら +f --。
# マウントポイント配下で開かれているファイル一覧 lsof +D /mnt/data # ブロックデバイス単位で見る(マウントポイントが既に壊れている場合に有効) lsof +f -- /dev/sdb1
lsof +D はツリー全体を stat するため大きなディレクトリでは遅い。素早く原因を掴むなら fuser -vm を先に、詳細確認に lsof を使うのが実務的。
掴んでいるプロセスを止めて外すには?
結論: まず原因プロセスを 正常終了(cd で抜ける / サービス停止 / TERM)させてから umount。それでも残るなら
fuser -kで強制終了するが、SIGKILL はデータ損失リスクがあるので最後の手段。
1. 安全な順序:自分で抜ける・止める
- 自分のシェルの cwd が中にあるだけなら、まず外に出る。
cd /
- サービスが掴んでいるなら、そのサービスを止める(kill より確実で安全)。
sudo systemctl stop myapp.service
- 個別プロセスは PID を確認して穏当なシグナルから。
kill 2890 # SIGTERM(後始末の余地を与える)
2. 最後の手段:fuser -k で一括終了
正常終了で抜けないプロセスは fuser -k でまとめて殺せる。ただし -k は既定で SIGKILL を送るため、書き込み中なら破損し得る。
# 中身を確認してから(-i で対話確認) sudo fuser -kim /mnt/data
/mnt/data: 2890c 2314c Kill process 2890 ? (y/N) y
-k… 利用プロセスにシグナル送信(既定 SIGKILL)-i… 1 件ずつ確認(事故防止に強く推奨)-m… マウント単位
fuser -km / のように ルートや稼働中の重要 FS に対して打つと、システム全体のプロセスを SIGKILL してサーバが落ちる。対象パスを必ず二度確認し、本番では -i を付けること。SIGKILL は書き込みバッファをフラッシュせず終了させるため、DB やログのデータ破損につながる。
プロセスを片付けたら再度 umount する。
sudo umount /mnt/data
それでも外れない:lazy / force umount は使ってよいか?
結論: 即座にツリーから切り離したいなら
umount -l(lazy)。応答しない NFS にはumount -f(force)。どちらも「掴んでいる側を解決しない」回避策なので、原因を放置したまま常用しないこと。
lazy umount(-l)
ファイルシステムを 今すぐツリーから外し、参照が消え次第クリーンアップする。掴んでいるプロセスを落とせない/落としたくない場合の緊急避難。
sudo umount -l /mnt/data
注意点:
- マウントポイントは見えなくなるが、開いていた FD は生きたまま(プロセスは古いファイルを掴み続ける)。完全な解放はプロセス終了後。
- 同じデバイスをすぐ再マウントすると、裏で残った参照と競合することがある。
- 未書き込みデータのフラッシュ完了を保証しない。重要 FS では原因解決を優先する。
force umount(-f)
主に 応答しない NFS 向け。サーバがダウンしてハングした NFS マウントを強制的に切り離す。
sudo umount -f /mnt/nfs
ローカルの ext4/xfs では -f はあまり効かない(busy の原因がローカルプロセスなので)。NFS のハングは 「Stale file handle」の対処 も併読。
プロセスが見当たらないのに busy なときは?
結論:
fuser/lsofに何も出ないのに busy なら、原因は「プロセスの開いたファイル」以外。入れ子マウント・swap・loop デバイス・NFS エクスポートの 4 つを順に疑う。
1. 入れ子マウント(bind / overlay)を確認
対象の 上にさらに別マウント が乗っていると busy になる。findmnt -R でツリーを見て、子マウントから順に外す。
findmnt -R /mnt/data
TARGET SOURCE FSTYPE OPTIONS /mnt/data /dev/sdb1 ext4 rw,relatime └─/mnt/data/cache tmpfs tmpfs rw
この場合は子の /mnt/data/cache を先に umount する。Docker の overlay や mount --bind でよく起きる。
2. swap として使われていないか
対象パーティションを swap に使っていると当然外せない。swapon --show で確認し、swapoff する。
swapon --show sudo swapoff /dev/sdb2
3. loop デバイスが掴んでいないか
イメージファイルを loop マウントしている場合、loop デバイス経由の参照が残る。losetup -a で確認して解放する。
losetup -a sudo losetup -d /dev/loop0
4. NFS でエクスポート中でないか
そのファイルシステムを NFS サーバとしてエクスポートしていると busy になる。exportfs で解除する。
sudo exportfs -ua # 全エクスポート一時解除
最短フロー: ① fuser -vm /mnt/data で誰が掴むか確認 → ② 正常終了(cd / systemctl stop / kill)→ ③ 再 umount → 残れば ④ findmnt -R・swapon --show・losetup -a で非プロセス要因を確認 → ⑤ 緊急時のみ umount -l。原因特定を飛ばさないのが事故防止の唯一の鍵。