もくじ
- 「また EBUSY…」さっきまで動いていたのに、なぜ今だけ “Device or resource busy” なのか
- EBUSY は“バグ”じゃない:カーネルが守っている不変条件(invariants)を言語化する
- まず切り分け:busy なのは「マウント」「ブロックデバイス」「ディレクトリ」「ロックファイル」のどれ?
- 占有者の特定:lsof / fuser / /proc で「誰が掴んでいるか」を可視化する
- 伏兵その1:カレントディレクトリ・bind mount・chroot・namespace が起こす“見えない使用中”
- 伏兵その2:dm-crypt / LVM / mdraid / loop など多段ストレージで busy が伝播する理由
- 伏兵その3:systemd、udev、snap、コンテナランタイム—“裏で動く自動化”のロックと遅延解放
- 再試行を設計する:一律リトライが事故る条件(永続 busy / 破壊的操作 / 競合)を見分ける
- 安全に通す実装パターン:drain→quiesce→実行→検証、バックオフ+期限+観測の制御ループ
- 帰結:EBUSY 対策の本質は「待つ」ではなく「状態を観測して、条件付きで前進する」こと
【注意】 本記事は一般的な情報提供です。実環境では構成・権限・稼働状況により手順が変わり、誤操作は停止やデータ損失につながります。判断に迷う場合や重要システムでは、株式会社情報工学研究所のような専門事業者に相談してください。
第1章 「また EBUSY…」さっきまで動いていたのに、なぜ今だけ “Device or resource busy” なのか
Ubuntuで作業していると、突然こう言われる瞬間があります。
「umount しようとしたら Device or resource busy」「ディスクを抜き差しできない」「古いディレクトリを消そうとしたら EBUSY (16)」。さっきまで普通に動いていたのに、なぜ今だけ“使用中”なのか。現場の感覚だと「誰も触ってないのに……」という苛立ちに近いものが出ます。
ただ、ここで大事なのは、EBUSYが“気まぐれ”に出ているのではなく、カーネルが「いまそれを外したり壊したりすると整合性が崩れる」という状態を検知して止めている、という点です。つまりEBUSYは“失敗”ではなく、“危険を回避するためのブレーキ”として出ています。ここを腹落ちさせると、対処が変わります。
たとえば、umount がEBUSYを返す代表的な状況は次のようなものです。
そのマウント配下に、まだ開いているファイル(open file)がある
誰かのカレントディレクトリ(cwd)がそのマウント配下にある
bind mount や別namespaceの参照が残っていて、表面上は見えないが利用中
ブロックデバイスが、LVM / dm-crypt / mdraid / loop などの下層として使われ続けている
現場のモヤモヤは「それ、どれなの?」が即答できないところから来ます。ここで闇雲に再試行を始めると、時間だけが溶けます。あるいは、強制解除(後述)を軽い気持ちでやってしまい、別の障害につながることもあります。
本記事は、EBUSYを“待てば直る現象”として扱うのではなく、「何がbusyなのか」「誰が掴んでいるのか」「busyが解消する条件は何か」を観測し、条件が整った時だけ前進する、という設計に落とし込みます。最終的には、スクリプトや運用手順として再現性のある“抑え込み”にするのがゴールです。
次章ではまず、EBUSYというエラーの意味を、プログラマーが納得できるレベルで“仕様”として言語化します。そこが伏線になって、後半の再試行設計に一本でつながります。
第2章 EBUSY は“バグ”じゃない:カーネルが守っている不変条件(invariants)を言語化する
EBUSYはLinux/UNIX系で広く使われるエラーで、要点は「その操作は、対象が使用中(busy)であるため実行できない」です。ここで重要なのは“使用中”が人間の感覚の「誰かが触ってる」だけではないことです。カーネル視点で「参照・利用の関係が残っている」なら使用中です。
プログラマーの世界に置き換えると、EBUSYは「参照カウントが0になっていない」「所有権(ロック)が解放されていない」「依存関係のグラフにまだエッジが残っている」ことを示します。これを無視して破壊的操作を許すと、整合性が壊れたり、予期せぬI/Oエラーやデータ損失に直結します。だからカーネルは止めます。
たとえば、マウント解除(umount)を例にすると、カーネルが守りたい不変条件は大きく次の2つです。
| 不変条件(守りたいこと) | 破ると何が起きうるか |
|---|---|
| マウント配下を参照中のプロセスがいない状態で解除する | 参照中のパスが突然消え、アプリがI/Oエラーや想定外の失敗を起こす |
| 書き込み途中のデータが安全に確定されている(遅延書き込み等の整合) | メタデータ不整合、ファイルシステム破損、復旧コスト増大 |
この不変条件を守るために、umountは内部で「まだ利用者がいるなら拒否する」という動きを取ります。ここで返ってくるのがEBUSYです。
また、“デバイス”側でも同じです。たとえばLVMやdm-cryptは、ブロックデバイスを下層として掴み続けます。表面上は「/dev/sdb を外したい」でも、実際には「その上に論理ボリュームがぶら下がっている」ため、カーネルにとっては依存が残っていてbusyです。ここでも不変条件(依存関係の整合)が伏線になります。
ここで一つ、「現場の心の会話」をそのまま書くならこうです。
「またEBUSY? じゃあリトライでいいでしょ。sleep入れて回しとけば、そのうち通るはず…」
この発想は自然です。ですが、busyが解消する条件を観測できていない状態での一律再試行は、(1)永遠に通らない、(2)通った瞬間に壊す、のどちらかになりがちです。後半で述べる“再試行設計”は、ここで言語化した不変条件を、チェック項目として実装することになります。
次章では、まず「busy なのはどの種類か」を切り分けるための見取り図を作ります。ここで分類できると、lsof/fuserへ一直線に進める場面と、多段ストレージ・自動化プロセスを疑う場面が分かれます。
第3章 まず切り分け:busy なのは「マウント」「ブロックデバイス」「ディレクトリ」「ロックファイル」のどれ?
EBUSYは“原因名”ではなく“状態名”なので、最初にやるべきは分類です。分類ができないと、調査コマンドも、再試行の条件も決められません。ここでは現場で遭遇しやすい4分類に落とします。
マウントがbusy:umountでEBUSY。典型は配下に開いているファイルやcwdがある。
ブロックデバイスがbusy:/dev/sdX や /dev/mapper/* を外したいのにEBUSY。LVM/dm-crypt/mdraid/loop等が絡みがち。
ディレクトリがbusy:削除(rmdir)や移動がEBUSY。多くはcwdやbind mount、あるいは別namespaceからの参照。
ロック・排他がbusy:アプリ/ミドルウェアがロックファイルやflockで拒否している(これはEBUSY以外の形で出ることもある)。
切り分けに使える、最小の観測ポイントを表にしておきます。
| 症状 | まず疑う対象 | 入口となる観測 |
|---|---|---|
| umount が EBUSY | マウント配下の open/cwd | lsof +D(重い場合あり) / fuser -vm |
| デバイスの取り外し・解除で EBUSY | LVM/dm-crypt/mdraid/loop | lsblk / dmsetup ls / lvs,pvs |
| ディレクトリ削除で EBUSY | cwd / bind mount / namespace | pwdx / mount / findmnt |
| 処理が“待ち”に入って進まない | 背後の自動化(systemd/udev等) | systemctl status / journalctl |
ここでのポイントは、「まず軽い観測で当たりを付け、重い調査は必要な範囲だけにする」ことです。例えば lsof +D はディレクトリ配下を総当たりするため、巨大なツリーで実行すると時間がかかります。そこで、次章ではより確実に“誰が掴んでいるか”へ到達できる手順を、lsof/fuserと/procの読み方をセットで整理します。
この“観測してから前進する”という姿勢が、そのまま後半の再試行設計の伏線になります。条件が見えないのに待つのではなく、条件を見える形にして、揃ったら進む。ここが本記事の軸です。
→→アンカー→h2…→本文→
第4章 占有者の特定:lsof / fuser / /proc で「誰が掴んでいるか」を可視化する
EBUSYで詰まるとき、最短で状況が動くのは「占有者(どのプロセスが掴んでいるか)」が特定できた瞬間です。ここが見えないと、再試行も、停止判断も、関係者への説明もできません。逆に言えば、見えてしまえば“やること”が急に具体的になります。
まず、umountがEBUSYになる典型は「マウント配下に open しているファイルがある」か「誰かの cwd が配下」かです。これを調べる道具として代表的なのが lsof と fuser です。
1) fuser:マウントを掴んでいるPIDを一発で出す
fuser は「このファイル/マウントを使っているプロセス」をPIDとして出してくれます。umount対象が明確なら、入口として強いです。
fuser -vm /mnt/target(マウントポイントを使っているプロセス一覧)fuser -vm /dev/sdX1(デバイスを使っているプロセス一覧:状況による)
出力にPIDとユーザー、アクセス種別が出るので、「誰が掴んでいる」「何のアクセスか」の当たりがつきます。ここで大事なのは、PIDが出たら即 kill ではなく、まず“そのプロセスが何をしているか”を確認することです。特にDBやストレージ管理系、バックアップ、コンテナランタイムなどは、止め方に作法があります。
2) lsof:開いているファイルの“中身”まで掘る
lsof は「どのプロセスが、どのファイル/ソケット/デバイスを開いているか」を詳細に出します。マウント配下に限定して調べたいときに使いますが、注意点として、ディレクトリツリーが大きいと重いことがあります。
lsof +D /mnt/target(配下を再帰的に探索:重い場合あり)lsof | grep /mnt/target(全体から絞り込み:環境により工夫)
lsofの利点は、PIDだけでなく、どのファイルを開いているか、FD番号、アクセスモードまで見えることです。「ログローテートが古いログを掴んだまま」「アプリが作業ディレクトリを掴みっぱなし」などが一目で分かることがあります。
3) /proc:最終的に“根拠”を押さえる
lsof/fuserでPIDが分かったら、/procで根拠を押さえると説明が通ります。特に“cwdが原因”のケースでは、/procの情報が直球です。
/proc/<pid>/cwd:そのプロセスのカレントディレクトリ(シンボリックリンク)/proc/<pid>/fd/:開いているファイルディスクリプタ一覧(リンク)/proc/<pid>/mountinfo:そのプロセス視点のマウント情報(namespace絡みの伏線)
たとえば、umount対象が /mnt/target で、あるPIDの /proc/<pid>/cwd が /mnt/target 配下を指していれば、それだけでEBUSYの根拠になります。「誰かがそこにcdしたまま」でもカーネルは安全側に倒れます。
ここで現場の“心の会話”が入りやすいポイントがあります。
「PIDは分かった。でも、それを止めていいの? 止めたら何が起きる?」
この不安は健全です。だから、次の章では“見えない使用中”を含め、busyを解消するための安全な手順(止め方・順序・確認)を、ストレージ/OSの視点で整理します。観測 → 対応 → 検証、という流れを崩さないのが重要です。
第5章 伏兵その1:カレントディレクトリ・bind mount・chroot・namespace が起こす“見えない使用中”
EBUSYが厄介なのは、利用者が“見えている”とは限らない点です。特に、マウントやディレクトリに関しては「表から見えていない参照」が残りやすく、ここを見落とすと、永遠に“そのうち通る”を続けることになります。
1) cwd:ただの cd でも busy になる
一番単純で多いのがこれです。誰かが /mnt/target 配下に cd したままターミナルを放置しているだけで、umountはEBUSYになります。プロセスは“何もしていない”ように見えても、cwdとして参照が残っています。
調べ方は第4章のとおりで、PIDが分かったら /proc/<pid>/cwd を見ます。ターミナルなら「誰のセッションか」まで追えます。ここで大事なのは、原因が分かったら“責める”のではなく、運用に落とすことです。例えば、メンテナンス時は対象マウント配下に入らない、入るなら撤収手順を明文化する、といった形です。
2) bind mount:同じ実体が別の場所から掴まれる
bind mountは便利ですが、トラブル時は“見えにくさ”の原因になります。/mnt/target を別のパスにbindしていた場合、umount対象そのものは意識から消えがちです。しかし実体は参照され続けます。
この場合、mount や findmnt で関連するマウントを洗い出すのが有効です。ポイントは「マウントポイントで探す」のではなく「実体(ソース)やパスの重なり」で探すことです。bindが残っているなら、解除順序も考える必要があります。
3) chroot / namespace:プロセスごとに見えている世界が違う
コンテナや一部の隔離環境では、プロセスごとにマウントnamespaceが異なります。その結果、ホスト側から見えるマウント一覧だけでは「もう誰も使っていないはず」と判断してしまうことがあります。しかし別namespace内で参照が残っていると、EBUSYは解消しません。
ここで効くのが、/procの mountinfo と、PID単位での観測です。ホストで見えないマウントが、あるPIDの /proc/<pid>/mountinfo では見えている、ということが起きます。コンテナ運用下では特に、ストレージが“どのコンテナに紐づいているか”まで追う必要があります。
この章の伏線は「見えない参照がある限り、再試行しても意味がない」です。だからこそ、再試行は“観測結果に基づく条件付き”にする必要があります。
次の章では、もう一段厄介な伏兵、多段ストレージ(dm-crypt/LVM/mdraid/loopなど)でbusyが伝播する構造を整理します。ここを理解すると「どの順序で解除すべきか」が自然に決まってきます。
第6章 伏兵その2:dm-crypt / LVM / mdraid / loop など多段ストレージで busy が伝播する理由
ブロックデバイス周りのEBUSYは、マウントのbusyより一段“構造的”です。というのも、ストレージはしばしば多段で構成されていて、上位が掴んでいる限り下位は解放できない、という依存関係があるからです。ここを理解せずに「/dev/sdb を外したい」だけで動くと、忙しさ(busy)の本当の起点に辿り着けません。
1) 依存関係を“木”で見る:lsblk がまず入口
多段ストレージの全体像を掴むのに、最初に使いやすいのが lsblk です。デバイスがどのように積み重なっているか(親子関係)が見えます。ここで重要なのは、対象デバイスが「どの上位に使われているか」を把握することです。
例えば、物理ディスク → パーティション → dm-crypt → LVM → ファイルシステム → マウント、のように積み上がっているなら、解除は基本的に“上から順”です。上位が残っているのに下位を外そうとすると、カーネルは不変条件を守るためにEBUSYで止めます。
2) 典型スタックと“どこがbusyになりやすいか”
| 構成要素 | busyになりやすいポイント | 観測の入口 |
|---|---|---|
| dm-crypt(暗号化) | 上位のLV/FSが残っていると解除不可 | lsblk, dmsetup |
| LVM(VG/LV) | LVがopen状態、あるいはFSがマウント中 | lvs/pvs/vgs, lsblk |
| mdraid(/dev/md*) | 上位で使用中、同期/再構築中の状態 | cat /proc/mdstat |
| loop(ループデバイス) | イメージファイルが利用中、マウントが残る | losetup -a, mount |
ここでの要点は、「busyの原因は“その段”だけにあるとは限らない」ということです。下位デバイスのEBUSYは、実際には上位のマウントやプロセス利用が原因であるケースが多いです。だから、対処も“上から解く”になるのが自然です。
ただし現場では、上位を解くこと自体が怖い場合があります。
「これ、サービス稼働中のLVだよね? 外していいの? 影響は?」
ここが、一般論だけでは危険になるポイントです。停止許容、冗長化、バックアップ、復旧手順、そしてデータ価値。これらの条件で最適解は変わります。後半で述べる再試行設計は、こうした“個別条件”を前提に、危険な一律運用を避けるための枠組みでもあります。
次章では、さらに“裏で動く自動化”(systemd/udev/コンテナランタイム等)がbusyや遅延解放を生むケースを扱います。ここは、観測していないと「何もしてないのにbusy」が続く温床になります。
第7章 伏兵その3:systemd、udev、snap、コンテナランタイム—“裏で動く自動化”のロックと遅延解放
「誰も触っていないのにbusyが続く」──この感覚の背後に、実際に“触っている”主体がいることが少なくありません。Ubuntuでは特に、systemdによるサービス管理、udevによるデバイスイベント処理、snapなどの仕組み、そしてコンテナランタイムが、ストレージやファイルを握り続けることがあります。
ここを見落とすと、現場の心の会話がこうなりがちです。
「……いや、lsofにもfuserにも出ない。じゃあ待てばいいの? でもいつまで?」
結論から言うと、待つ前に“裏で動く自動化の状態”を観測すべきです。観測しない待機は、単なる時間消費になり得ます。
1) systemd:停止したつもりでも、プロセスが残る/再起動する
systemd管理下のサービスは、停止・再起動・自動再起動(Restart=)などの設定により、こちらの意図と違う挙動をする場合があります。例えば、サービス停止を依頼したのに、依存関係や監視で再起動されてしまい、結果として対象ディレクトリやソケット、ログファイルが掴まれ続けます。
このときは、次の観測が役に立ちます。
systemctl status <service>:いま稼働しているか、再起動が走っていないかsystemctl show <service>:Restart設定や依存関係の把握(必要に応じて)journalctl -u <service> --since "...":直近の停止・再起動の痕跡
ここで重要なのは、EBUSYの原因が「ファイル」ではなく「サービスの生存戦略」になっていることがある点です。ファイル単体を追っても埒が明かない場合、サービス単位で止める・無効化する・メンテナンスモードに入れる、といった“制御”が必要になります。
2) udev:デバイスイベントが走り、デバイスを一時的に触る
udevはデバイスの追加・削除・状態変化に反応してルールを実行します。ストレージの抜き差しや再認識が絡む作業では、udevが裏で処理を走らせ、その間にデバイスが“使用中”に見えることがあります。
この場合、busyは一時的なこともありますが、「一時的かどうか」を判断するにはログ観測が必要です。journalにデバイス関連のログが残ることもありますし、作業の直後に何が動いたかを時系列で追うことが有効です。
3) snap/自動更新:想定外のタイミングでプロセスが出入りする
snapを利用している環境では、自動更新やサービス再起動が絡むことがあります。これ自体は一般的な仕組みですが、メンテナンス時間帯と重なると「止めたはずのものが動く」「更新が走ってファイルを掴む」といった形でbusyの原因になり得ます。
ここでの実務上のポイントは、作業時間帯を揃える(更新を避ける)、メンテナンスウィンドウで必要な抑制設定を検討する、といった運用面の“歯止め”です。技術だけでなく、運用としての落としどころが必要な領域です。
4) コンテナランタイム:ホストから見えない参照が残る
コンテナ環境では、bind mountやnamespaceの話がそのまま現実になります。ホスト側でumountしたいのに、コンテナがそのボリュームを掴んでいる、というケースです。これは「ホストの観測だけでは不十分」になりやすい領域です。
この状況で大切なのは、コンテナの停止・再配置・ボリュームの切り替えなど、ランタイム側の制御手順を持っているかどうかです。EBUSYを“その場しのぎ”で回避すると、別の障害(アプリ側のI/O失敗)につながり得ます。
第7章の帰結はシンプルです。busyの原因が「人間が見ているプロセス」だけとは限らない。だから、再試行や強制解除の前に、systemd/journalなどで“裏の動き”を観測し、制御できる単位(サービスやコンテナ)で対処する必要があります。
次章では、ここまでの伏線を回収して、「再試行」がなぜ危険になりうるのかを、事故が起きる条件として整理します。闇雲なリトライを卒業し、条件付きで前進する設計へ繋げます。
第8章 再試行を設計する:一律リトライが事故る条件(永続 busy / 破壊的操作 / 競合)を見分ける
「EBUSYならリトライ」──現場で最初に出る発想として自然です。実際、一時的なbusy(短時間で解消する自動処理)なら、短い待機で通ることもあります。
ただし、再試行を“思考停止”で入れると危険です。ここでは、事故や長期停滞につながる典型条件を3つに整理します。これは後半の安全な再試行設計に直結します。
条件1:永続 busy(解消条件が揃わない)
busyが解消しないのは、単に時間が足りないのではなく、解消条件が満たされていないからです。例えば、サービスが稼働し続けていてログを掴み続ける、コンテナがボリュームを使い続ける、あるいは運用ルールとして常時利用しているマウントである、などです。
この場合、いくらsleepしても状況は変わりません。必要なのは「どの条件が満たされていないか」を観測し、条件を満たすための制御(停止・切替・drain)を実施することです。第4〜7章の観測がここで生きます。
条件2:破壊的操作(通った瞬間に壊す可能性がある)
umount、デバイスの切り離し、暗号化層の解除、LVMの無効化などは、通った瞬間に影響が出る操作です。リトライで“たまたま通った”結果、アプリが想定外のI/O失敗を起こす、整合性が壊れる、といった事故につながり得ます。
ここで必要なのは、「通ってよい状態か」を判定するゲートです。たとえば、対象サービスが停止している、I/Oが止まっている、業務影響が許容範囲、復旧手順が準備済み、など。一般論では決められないので、運用設計とセットになります。
条件3:競合(複数の自動化が同じ資源を取り合う)
例えば、メンテナンススクリプトがumountを試みる一方で、監視や自動復旧が再マウントする。あるいは、バックアップジョブが同じディレクトリを触り続ける。こうなると、忙しさ(busy)が“自然に復活”します。
この場合、再試行は火に油です。必要なのは、競合を抑える仕組み(メンテナンスモード、排他ロック、ジョブスケジューラの制御、systemdの一時停止など)です。つまり、単なる技術コマンドではなく、運用としての防波堤が必要になります。
ここでのまとめは「リトライは万能ではない」です。リトライは“観測に基づく条件付き前進”の一部として機能します。逆に、観測がないリトライは、永遠に通らないか、通った瞬間に事故るか、競合で不安定化するかのどれかになりやすい。
次章では、この結論を具体の設計に落とします。drain→quiesce→実行→検証という順序、バックオフと期限、観測とログ化まで含めて「安全に通す」パターンを作ります。
第9章 安全に通す実装パターン:drain→quiesce→実行→検証、バックオフ+期限+観測の制御ループ
ここまでの話をまとめると、EBUSY対策は“コマンドの小技”ではなく、「状態を観測して、条件が揃ったら前進する」制御の設計です。ここでは、現場で使える形に落とし込みます。
1) パターン全体像:drain→quiesce→実行→検証
用語の意味を簡単に整理します。
| 段階 | 目的 | 典型アクション |
|---|---|---|
| drain | 新規利用を止める | メンテナンスモード、ジョブ停止、LB切り離し、スケジューラ停止 |
| quiesce | 既存利用を“静かに終わらせる” | サービス停止、I/O収束、バッファ同期、セッション終了 |
| 実行 | 目的操作(umount/切離し等)を行う | umount、cryptsetup/lvchange/losetup解除など |
| 検証 | 成功を確認し、次の工程へ進める | findmnt/lsblkで状態確認、ログ確認、再発防止チェック |
EBUSYが出るのは、多くの場合「drain/quiesceが不足」か「検証が曖昧」かです。つまり、手順のどこかが省略されていることが多い。だから、設計として段階を持ちます。
2) 観測点を“ゲート”にする:通ってよい条件を定義する
第8章で述べた「破壊的操作」の怖さは、通った瞬間に影響が出ることです。そこで、実行前に必ず満たすべき条件を、観測で判定します。例として、umount前のゲートを挙げます。
対象サービスが停止している(systemdの状態、プロセス存在)
対象マウント配下のopen/cwdがゼロに近い(fuser/lsofで確認)
競合する自動化が抑制されている(ジョブ停止、再起動抑制)
ここで重要なのは、“ゼロでないと絶対ダメ”と決めつけないことです。例えば、監視が軽く触る程度なら許容するケースもあります。しかし、それを許容するなら「何を許容するか」を明文化しないと、後で事故ります。つまり、ゲート条件は個別案件の設計に依存します。
3) バックオフ+期限:再試行は制御ループとして実装する
再試行を入れるなら、次の3点をセットにします。
バックオフ:一定間隔ではなく、状況に応じて待機(例:指数的に待機を増やす)
期限(タイムアウト):無限に待たず、どこで人間判断に切り替えるか決める
観測ログ:なぜ通らないかの根拠をログに残す(後で改善できる)
これにより、単なる“待ち”が、改善可能な運用知に変わります。例えば、一定時間通らないときは、fuserの出力を記録して関係者に通知する、あるいはメンテナンス窓を延長する判断材料にする、といった使い方ができます。
4) 「一般論の限界」を越えるポイント:影響と復旧の設計
ここまで書いたパターンは一般的に有効ですが、どこまで安全側に寄せるかは環境と契約条件で変わります。停止許容が数秒なのか、数分なのか。冗長化があるのか。データ価値がどれほどか。復旧に何時間かかるのか。
この判断を誤ると、EBUSYを回避しても別の損失につながります。だから、終盤では「一般論の限界」を明確にし、個別案件では専門家に相談すべき理由を整理していきます。
次章(最終章)では、この記事の帰結として、EBUSY対策の本質を一文でまとめ、さらに“現場で迷う具体ポイント”を整理します。その後に、指定どおり「現在のプログラム言語各種にそれぞれの注意点」を付録としてまとめます。
第10章 帰結:EBUSY 対策の本質は「待つ」ではなく「状態を観測して、条件付きで前進する」こと
ここまでの章で繰り返し出てきた結論を、あえて一文にまとめます。
EBUSYは“邪魔”ではなく、カーネルが整合性を守るために踏ませているブレーキであり、対策の本質は「状態を観測し、解消条件が揃ったときだけ次に進む」ことです。
この一文が腹落ちすると、現場の動きが変わります。たとえば、umountでEBUSYが出たとき、以前は「sleepして再試行」を繰り返していたかもしれません。ですが本質に沿うなら、まず次の問いを立てます。
何がbusyなのか(マウントなのか、デバイスなのか、ディレクトリなのか)
誰が掴んでいるのか(lsof/fuser、/procで根拠を押さえる)
busyが解消する条件は何か(サービス停止、コンテナ撤収、上位層の解除、競合抑制など)
通ってよい状態か(破壊的操作なら、影響・復旧・契約条件を含めた判断)
この問いに答えられないままリトライすると、第8章で整理した通り「永続busyで止まる」「通った瞬間に別の障害を呼ぶ」「競合で不安定化する」のどれかに寄りやすい。だから、観測→制御→検証を“型”として持つのが強いです。
もう少し現場寄りに、典型シナリオを3つだけ短く整理します。
シナリオA:umountがEBUSY(原因がcwdだった)
fuserでPIDが出た。/proc/<pid>/cwdを見ると、たまたま担当者のシェルが配下にいた。これは「人間の作業ルール」で再発します。対策はコマンドの工夫より、メンテナンス手順に“撤収確認(cwd確認)”を入れることです。ここは運用の「歯止め」で再発率が下がります。
シナリオB:デバイス解除がEBUSY(上位層が残っていた)
/dev/sdXを外したいがbusy。lsblkで見るとdm-crypt→LVM→マウントがぶら下がっていた。対策は“上から順”にdrain/quiesceして解除することです。下位から外そうとするほど、ブレーキが強くかかります。ここは構造理解がそのまま手順になります。
シナリオC:誰も触っていないのにbusy(裏の自動化が触っていた)
systemdの再起動設定やバックアップジョブ、コンテナの再スケジュールが、こちらの作業と競合していた。対策は「競合する自動化を抑える」ことです。単発のコマンドで解くのではなく、メンテナンスモードやジョブ抑止で“場を整える”のが効きます。
そして、ここがBtoBの現場で一番大切な話になります。
EBUSY自体は一般論で整理できますが、「通してよいか」「どこまで止められるか」「失敗時にどう復旧するか」は個別案件の条件で変わります。たとえば、医療・介護など止められないシステム、ログや証跡が重要なインシデント対応、暗号化やRAID、仮想化が絡む多段構成では、判断を誤ると“EBUSYを避けた代償”が非常に大きくなります。
だからこそ、終盤の結論としてはこうなります。
一般論の手順は「観測と型」を提供できますが、個別案件の最適解は、構成・停止許容・契約・復旧条件を踏まえて設計し直す必要があります。
もし、
本番稼働中で止められない/止める判断の根拠が必要
dm-crypt / LVM / RAID / 仮想化 / コンテナなどが絡み、依存関係が複雑
作業の失敗がデータ損失や長時間停止につながる(データ価値が高い)
インシデント対応やフォレンジックで“証跡保持”が必須
といった状況なら、株式会社情報工学研究所のような専門家に相談し、手順を“現場の条件”に合わせて組み替えるのが結果的に早く、安全です。観測ログや現状の構成情報が揃っていれば、原因特定も再発防止も、より具体的に前へ進められます。
付録:現在のプログラム言語各種における EBUSY まわりの注意点(実装・運用)
EBUSYの“正体”はOS側の状態なので、言語が違っても本質は同じです。違いが出るのは「エラーの見え方」「再試行の書きやすさ」「リソース解放の落とし穴」「並行実行時の競合」の4点です。ここでは、現場で混乱しやすい注意点を言語別にまとめます。
共通の前提:やってはいけない“雑なリトライ”
どの言語でも、次の3点が揃っていないリトライは危険です。
期限:無限ループにしない(いつ人間判断へ切り替えるか決める)
バックオフ:一定間隔ではなく待機を増やす(負荷・競合を悪化させない)
観測ログ:誰が掴んでいるか/何がbusyかを記録して改善できる形にする
また、umountやデバイス解除など破壊的操作は、実行前に「通してよい状態か」を判定するゲート(第9章)を必ず持つべきです。
C / C++:errnoの扱いと“解放漏れ”が致命傷になりやすい
errnoの取り扱い:失敗直後にerrnoを読む。別の関数呼び出しで上書きされやすい。
close漏れ:ファイルディスクリプタのclose漏れは、busyを自分で作る代表例。例外や早期returnの経路で漏れやすい。
fork/exec後のFD継承:FD_CLOEXECを付けないと子プロセスがFDを持ち続け、umountが永遠に通らないことがある。
排他制御:flock/fcntlロックを使うなら、ロック解放タイミングと異常終了時の挙動を理解する(ロックはプロセス終了で解放されるが、設計次第で“待ち行列”が詰まる)。
Go:エラーはラップされる。タイムアウトとコンテキストを標準化しやすい
エラー比較:Goのerrorはラップされることがあるため、単純な文字列比較に頼らない。OSエラーを判定したい場合は、ラップ構造を意識して取り出す。
contextで期限を統一:再試行ループにcontextの期限を入れやすい。無限待ちを避ける設計に向く。
並行実行:goroutineで並列にメンテを走らせると、競合を自分で作りやすい。排他(ロック・単一フライト)を入れ、メンテナンスの“場”を整える。
Rust:stdだけだとOSエラーの判定が回り道になりがち
raw_os_error:
std::io::ErrorからOSエラー番号を取り出して判定する場面がある。扱いを統一しないと、実装ごとに分岐が散る。所有権で解放漏れは減る:RAIIでclose漏れは起きにくい一方、長寿命のハンドル(グローバル保持)があるとbusyを長引かせる。
外部コマンド連携:umountやlsof/fuserを呼ぶなら、戻り値・標準エラーの扱いを設計し、観測ログとして残す。
Java:例外が抽象化されやすい。ファイルロックとプロセス管理に注意
例外の層:
java.nio.file系は例外が抽象化され、根っこが“busy”でも表現が変わることがある。ログには原因(cause)まで出す。FileLock:
FileChannelのロックは、解放タイミングとfinallyの書き方が重要。ロック保持が長いと他工程が詰まる。外部プロセス:Process起動でパイプ(stdin/stdout)を閉じないと、子プロセスが生き残ったり、資源が解放されないことがある。終了待ちとクリーンアップを徹底する。
Python:with文でも“プロセス”と“スレッド”の後始末が残りやすい
コンテキストマネージャ:ファイルはwithで閉じやすいが、サブプロセス(subprocess)やスレッドがファイル/ディレクトリを掴む構造だとbusyが残る。
subprocessの注意:
Popenのパイプを適切にcloseしないと待ち合わせが詰まる。メンテ系は「期限」「強制終了」「ログ回収」を一体で設計する。再試行の書きやすさ=事故りやすさ:簡単にリトライが書ける分、観測なしのループを作りがち。必ず“なぜ通らないか”を記録する。
Node.js(JavaScript):非同期I/Oで競合しやすい。例外の握りつぶしに注意
Promiseチェーン:catchで握りつぶすと原因が消える。EBUSY系は、何を触っていたか(パス、PID、タイミング)を残す。
並列処理:複数の非同期タスクが同じパスを触ると、自分でbusyや競合を作る。キュー化や排他が必要。
外部コマンド:umount/lsof/fuserを呼ぶ場合、終了コード・stderrをログ化し、観測→判断の材料にする。
PHP:スクリプトは短命でも、バックグラウンドや権限境界で詰まりやすい
権限と所有者:Web実行ユーザーが触れる範囲が限定され、調査コマンドが実行できないことがある。観測は運用ホスト側で行う設計が必要。
ファイル操作:rename/unlinkが失敗したときに“後で通るだろう”で流すと不整合が溜まる。失敗時の復旧手順(再キュー・通知)を用意する。
C#(.NET):例外情報は豊富だが、運用ログに落とさないと現場で再現できない
IOExceptionの扱い:例外を捕まえるだけで終わらせず、対象パス、実行ユーザー、タイミング、再試行回数をログに残す。
バックグラウンドサービス:Windowsサービス的な設計をLinuxでも踏襲すると、長寿命プロセスがリソースを掴み続ける。メンテ時のdrain/quiesceを設計に入れる。
Bash / Shell:手早いが、強制操作の一発が重い。必ず“確認ステップ”を挟む
確認の徹底:
fuserやlsofの結果を見ずに強い操作へ進まない。ログと再現性:その場のコマンド履歴だけだと再発防止にならない。実行したコマンドと結果(観測ログ)を残す。
メンテの型:drain→quiesce→実行→検証をスクリプト化するなら、期限・バックオフ・失敗時の通知を組み込む。
最後に、付録の結論も一文でまとめます。
言語ごとの差はあっても、EBUSY対策は「観測・条件・制御・検証」の設計問題です。 そして、その設計は停止許容やデータ価値、冗長化、契約条件に強く依存します。
もし「このケースは止めていいのか」「どこまで抑え込みを入れるべきか」「復旧や証跡をどう担保するか」で迷うなら、一般論のまま進めず、株式会社情報工学研究所のような専門家に相談して、現場条件に合わせた手順・スクリプト・運用ルールまで含めて組み直すのが安全です。
はじめに
Ubuntuを運用する上で避けて通れないトラブルの一つに、デバイスやリソースが使用中であることを示すエラー、「EBUSY(エビジー)」があります。このエラーは、特定のデバイスやファイルが他のプロセスによってロックされている場合に発生し、作業の妨げとなることがあります。特に、システム管理者やIT部門の担当者にとって、この問題の原因を理解し、適切な対処法を知ることは重要です。この記事では、「Device or resource busy」エラーが発生した際の基本的な原因と定義から始め、その解決策や再試行のポイントについて詳しく解説します。システムの安定運用を維持し、迅速に問題解決を図るための実践的な知識を提供し、頼れるデータ復旧の専門家としての視点も交えながら、安心してシステム管理を行うためのサポートを目指します。
「EBUSY(エビジー)」エラーの原因は、システム内部のリソースやデバイスが他のプロセスによって既に使用中であることに起因します。具体的には、ファイルシステムのロックやデバイスのアクセス権限、またはシステムのリソース管理の問題が関係しています。例えば、あるファイルを別のプロセスが開いている状態で、そのファイルに対して操作を行おうとすると、システムは「デバイスまたはリソースが使用中である」と判断しエラーを返します。 このエラーは、システムの正常な動作の一環として発生することもあります。たとえば、バックアップやマウント作業中に同じリソースにアクセスしようとした場合や、リソースの解放が遅れている状態で再操作を試みた場合に起こります。システム管理者やIT担当者は、まずこのエラーが何に起因しているのかを正確に理解することが重要です。原因の特定には、プロセスの状態やリソースの使用状況を確認するコマンドやツールの活用が有効です。 この章では、エラーの根本原因を把握し、システムの動作原理を理解することが、適切な解決策を選択する第一歩となることを解説します。システムのリソース管理は複雑であり、誤った操作や無理な再試行はさらなる問題を引き起こす可能性もあるため、慎重な対応が求められます。
詳細な事例や具体的な対応方法に焦点を当てることで、「EBUSY」エラーの解決に向けた実践的な知識を深めていきます。たとえば、システム管理者がよく直面するケースの一つに、ディスクのアンマウントやファイルのロック解除があります。これらの操作は、適切なコマンドと手順を理解していなければ、逆にシステムの安定性を損なうリスクも伴います。 具体的には、`lsof`コマンドや`fuser`コマンドを用いて、どのプロセスが対象リソースを使用しているかを特定します。`lsof`は、開いているファイルやデバイスの一覧を表示するツールです。例えば、`lsof /dev/sdX`と入力すれば、そのデバイスを使用しているプロセスを確認できます。`fuser`も同様に、特定のリソースにアクセスしているプロセスIDを特定し、必要に応じて停止させることが可能です。 ただし、これらの操作はシステムの動作に影響を与える可能性があるため、慎重に行う必要があります。誤って重要なプロセスを停止すると、システムの安定性に支障をきたす恐れもあります。そのため、操作前には必ずバックアップやシステムの状態確認を行い、必要に応じて専門家の助言を仰ぐことが望まれます。 また、リソースの解放やロック解除がうまくいかない場合には、システムの再起動を検討するケースもあります。ただし、再起動は一時的な解決策であり、根本原因の特定と適切な対応策の実施が必要です。システムの動作状況やリソースの状態を継続的に監視しながら、問題の再発を防ぐための運用ルールを確立することが重要です。 こうした具体的な対応策を理解し、適切に実行できることが、「EBUSY」エラーの早期解決とシステムの安定運用に繋がります。システムの状態把握と適切な操作を行うためには、日常的な監視と管理の習慣化が不可欠です。
システム管理者やIT担当者が「EBUSY」エラーに直面した際に、最も重要なことは、原因の特定と適切な対応策の選択です。前述のコマンドを使用し、どのプロセスが対象リソースを使用しているかを把握した後、次のステップに進みます。 まず、`lsof`や`fuser`を用いて特定したプロセスに対して、必要に応じて停止や終了を促す操作を行います。例えば、`fuser -k /dev/sdX`コマンドは、そのデバイスを使用しているすべてのプロセスを強制的に停止させることができます。ただし、この操作はシステムの安定性に影響を与える可能性があるため、慎重に実行し、事前にバックアップを取ることが推奨されます。 また、デバイスのアンマウントも重要な対応策の一つです。`umount`コマンドを用いて、対象のデバイスを安全に切断しますが、`umount`が失敗した場合は、`lazy unmount`オプション(`umount -l`)を利用して、システムが使用中の状態のままデバイスを切断することも可能です。ただし、これも慎重に行う必要があります。 さらに、リソースのロックや使用状況を監視し続けるために、システムのログや監視ツールを活用して異常を早期に検知し、再発防止策を講じることも重要です。たとえば、定期的なシステム監査やリソース使用状況のレポート作成を習慣化し、潜在的な問題を未然に防ぐことが望まれます。 これらの対応策は、単一の操作だけでなく、総合的なシステム管理の一環として実施することにより、「EBUSY」エラーの発生頻度を低減させ、システムの安定性を維持します。システムの動作を継続的に監視し、迅速に適切な対応を行うことが、トラブルの拡大を防ぎ、円滑な運用を支える鍵となります。
「EBUSY」エラーの根本的な解決策として、リソースの適切な管理とシステムの運用改善が不可欠です。具体的には、リソースの使用状況を常に把握し、不要なプロセスや不要なリソースのロックを未然に防ぐことが重要です。これには、システム監視ツールの導入や定期的な状態確認が効果的です。 また、作業前の準備として、システムのバックアップを確実に行い、万一のトラブル発生時に迅速に復旧できる体制を整えておくことも推奨されます。これにより、強制的な操作や再起動が必要となった場合でも、データ損失やシステム障害のリスクを最小限に抑えることが可能です。 さらに、リソース管理の自動化や最適化を行うために、スクリプトや管理ツールを活用し、リソースの使用状況やロック状態を定期的に監視し、異常があればアラートを出す仕組みを導入することも効果的です。これにより、管理者は迅速に対応策を講じることができ、エラーの再発を防止します。 システムの運用においては、一定の運用ルールや手順を確立し、スタッフ全員が共通の理解のもとに作業を行うことも重要です。これにより、誤操作や無計画な操作によるリソースのロックやエラーの発生を抑制し、システムの安定性を高めることができます。 最後に、問題が解決しない場合や複雑な状況に直面した場合には、専門的なサポートやデータ復旧の専門業者に相談することも選択肢として考慮してください。確かな知識と経験を持つ専門家の助けを借りることで、迅速かつ安全に問題を解決し、システムの安定運用を維持することが可能です。 これらの取り組みを継続的に実施し、システムの健全性を保つことが、「EBUSY」エラーの根本的な解決と、システムの信頼性向上に繋がります。
システムの安定運用を継続するためには、定期的な監視と予防策の徹底が欠かせません。リソースの過剰な使用やロック状態の発生を未然に防ぐため、監視ツールやアラートシステムの導入が効果的です。これにより、異常を早期に検知し、迅速な対応を可能にします。また、運用ルールや手順を明文化し、スタッフ全員が共通理解のもとに作業を行うことも重要です。誤操作や無計画な操作によるリソースのロックを防ぎ、システムの信頼性を高めることができます。 さらに、定期的なシステムのバックアップとメンテナンスを行うことで、万一のトラブル時にも迅速に復旧できる体制を整えることが不可欠です。これにより、再起動や強制操作によるデータ損失やシステム障害のリスクを最小限に抑えられます。必要に応じて、管理スクリプトや自動化ツールを活用し、リソースの状態監視や異常検知を自動化することも効果的です。 また、複雑なケースや解決が難しい場合には、信頼できる専門業者やサポート窓口に相談することも検討してください。専門的な知識と経験を持つ技術者の助けを借りることで、問題の根本原因を特定し、安全に解決へと導くことができ、システムの信頼性と安定性を維持できます。 これらの継続的な取り組みは、システムの健全性を保ち、「EBUSY」エラーの再発を防ぐだけでなく、全体の運用効率を向上させることにもつながります。結果として、システムの信頼性が高まり、業務の円滑な進行と情報資産の保護につながるため、日常の管理体制の見直しと改善を意識的に進めていくことが重要です。
「Device or resource busy」エラー、すなわち「EBUSY」は、システム内部のリソースやデバイスが他のプロセスによって既に使用中であることに起因します。原因の特定には、`lsof`や`fuser`といったコマンドを用いて、どのプロセスが対象リソースを占有しているかを確認することが基本です。適切な対応策としては、対象プロセスの停止やリソースのアンマウント、必要に応じた再起動などがあり、これらを慎重に行うことが重要です。システムの安定性を保つためには、リソース管理の自動化や定期的な監視、バックアップ体制の整備も欠かせません。万一、問題が解決しない場合や複雑なケースには、専門的なサポートを受けることも選択肢です。継続的な監視と適切な運用改善を通じて、エラーの再発を防ぎ、システムの信頼性を維持することが、安定したシステム運用の基本となります。これらの取り組みは、システム管理者やIT担当者が安心してシステムを運用し、データ資産を守るために不可欠です。
システムの安定運用には、日々の継続的な監視と適切な対応策の実施が欠かせません。もし、「Device or resource busy」エラーが頻繁に発生している場合は、まずは専門的な知識を持つサポートやデータ復旧の専門業者に相談されることをおすすめします。経験豊富な専門家の助言やサポートを受けることで、根本原因の特定と迅速な解決が可能となり、システムの信頼性を維持できます。 また、当社では、データ復旧やシステム安定化に関する情報やサポートを提供しています。お困りの際には、遠慮なくお問い合わせください。専門のスタッフが、適切なアドバイスとサポートを通じて、システムの安心運用にお役立ていただけるよう努めております。システム管理の負担を軽減し、データ資産を守るための一助となれば幸いです。
「EBUSY」エラーに対処する際には、いくつかの重要な注意点を理解しておく必要があります。まず、リソースの強制解放やプロセスの停止を行う場合には、システムの安定性やデータの整合性に影響を与える可能性があるため、慎重に操作を進めることが求められます。特に、重要なシステムプロセスやサービスを誤って停止すると、システムの正常な動作に支障をきたす恐れがあります。 次に、再起動や強制的なアンマウントは一時的な解決策として有効ですが、根本的な原因を解消しない限り、同じエラーが再発するリスクがあります。したがって、その都度の対応だけに頼るのではなく、原因究明と恒久的な対策を併せて行うことが重要です。 また、操作前には必ずバックアップを取ることを推奨します。特に、重要なデータやシステム設定を変更する場合には、万が一のトラブルに備えた準備が必要です。これにより、誤操作や予期せぬ事態が発生した場合でも、迅速に復旧できる体制を整えることができます。 さらに、システムの監視やログの確認は日常的に行うべきです。異常を早期に発見し、適切な対応を取るためには、継続的な監視と記録が不可欠です。これらの注意点を守ることで、システムの安定性と信頼性を高め、トラブルの未然防止につなげることが可能となります。
補足情報
※株式会社情報工学研究所は(以下、当社)は、細心の注意を払って当社ウェブサイトに情報を掲載しておりますが、この情報の正確性および完全性を保証するものではありません。当社は予告なしに、当社ウェブサイトに掲載されている情報を変更することがあります。当社およびその関連会社は、お客さまが当社ウェブサイトに含まれる情報もしくは内容をご利用されたことで直接・間接的に生じた損失に関し一切責任を負うものではありません。
