ディスク容量不足解消のためクリーンアップ、まだ終わっていなかった山市良のうぃんどうず日記(152)(1/2 ページ)

前回は更新、シャットダウン、再起動に異様に時間がかかるMicrosoft Azure上のWindows Server 2016仮想マシンの問題の改善を試みました。その際に実行した「コンポーネントストア」のクリーンアップは、筆者の経験上、果てしなく時間がかかり、Azureの課金が心配だったので断念しました。今回はその経験の話。なぜかWindows 7のディスク不足も巻き込む一騒動でした。

» 2019年05月07日 05時00分 公開
[山市良テクニカルライター]
「山市良のうぃんどうず日記」のインデックス

山市良のうぃんどうず日記

ディスクの容量不足で2019年3月の更新ができない!

 その一騒動は、オンプレミスの「Windows Server 2016」を実行する物理マシンで、2019年3月の定例更新日に「Windows Update」で更新の確認を開始してすぐに始まりました。3月の品質更新プログラムをダウンロードするための空き領域が足りないと言われ、更新を続行できなかったのです(画面1)。

画面1 画面1 C:ドライブの空き領域不足により、品質更新プログラムのダウンロード前にブロックされてしまった

 エクスプローラーでC:ドライブの状況を確認したところ、約40GBのボリュームの空き領域が残り1GBほどになっており、使用領域を示すインジケーターは真っ赤になっていました。

 この物理マシンは「Windows 7」「Windows 8.1」、Windows Server 2016のマルチブート環境になっている古いノートPC。検証用に残しているレガシーなWindows環境と、Windows Server 2016のドメインコントローラー環境です。

 Windows 7とWindows 8.1は2つある物理HDDにそれぞれインストールしてありますが、Windows Server 2016はVHDブート環境としてインストールしてあり、VHDXファイルはWindows 7のOSディスク上に配置してあります。Windows Server 2016の初期のインストールメディア(ビルド14393.0ベース)を使用した新規インストールでは15GB程度でした。インストールしているサーバの役割や機能(Active DirectoryドメインサービスやIIS《Internet Information Services》が有効)も関係していると思いますが、いつの間にか40GBのほぼ全てを使っていました。

 VHDブート環境の利点の一つは、ディスク領域が足りなくなったとしてもVHDまたはVHDXファイルに追加の領域を割り当て、VHD/VHDX内のボリュームを拡張できることです。

 しかし、この古いノートPCはローカルディスクの空き容量自体が不足気味であり、大きなサイズを追加できません(容量可変タイプのVHD/VHDXだったとしても、割り当てサイズは配置先のボリュームの空き領域を超えることはできません)。何とか6GBだけ追加して、VHDブート環境のC:ドライブの空き領域を増やし、Windows Updateを完了させることができました。

ディスク不足解消のため「コンポーネントストア」のクリーンアップに4時間超

 VHDブート環境のWindows Update後、46GBボリューム(VHD/VHDXの割り当てサイズ)の空き領域は6.54GBになりました。これではまた近い将来、空き領域不足に陥るのは自明のこと。VHDXファイルの配置先となっている、Windows 7がインストールされているボリュームについては後で空き領域を何とか増やすとして、まずはVHDブート環境のOSディスクの空き領域を増やすことを考えました。

 しかし、このWindows Server 2016の現在の役割を維持したまま、大きな効果を期待できるほど削除できるデータやアプリケーションはありません。「ディスククリーンアップ」(Cleanmgr.exe)で削除できる項目くらいしか思い付きません。

 「ディスククリーンアップ」画面で「システムファイルのクリーンアップ」をクリックして表示される「Windows Updateのクリーンアップ」項目を削除すれば、数GBの領域を確保できると思いましたが、なぜか、このWindows Server 2016には「Windows Updateのクリーンアップ」が表示されませんでした。以前(初期のころ)は確かに存在しました。「3.99TB」とサイズを誤表示する問題があったので覚えているのです。

 ただし、「1MB」と誤表示するWindows Server 2016の別の仮想マシンが1台だけありました。誤表示と判断したのは、「1MB」の「Windows Updateのクリーンアップ」の削除に6時間以上かかり、数GBの領域が解放されたからです(それは今回とは別の話)。

 Windows Server 2016の「ディスククリーンアップ」から「Windows Updateのクリーンアップ」が消えてしまった理由は分かりませんが、それは問題ではありません。そもそも、Server Coreインストールの場合は「ディスククリーンアップ」自体利用できないからです。

 「ディスククリーンアップ」を使用しなくても、「DISM」コマンドで「コンポーネントストア(C:\Windows\WinSxS)」をクリーンアップすることができます。具体的には、以下のいずれかのコマンドラインを実行します。「/ResetBase」オプション付きの方が、より多くの空き領域の解放を期待できます。なお、「/ResetBase」が付かない方は、タスクスケジューラで定期実行される「\Microsoft\Windows\Servicing\StartComponentCleanup」タスクと同等の処理を行うようですが、「StartComponentCleanup」タスクは1時間でタイムアウトになり、終了してしまいます。以下のいずれかのコマンドラインを手動で実行する方が確実です(画面2)。

DISM /Online /Cleanup-Image /StartComponentCleanup

 または

DISM /Online /Cleanup-Image /StartComponentCleanup /ResetBase
画面2 画面2 「DISM /Online /Cleanup-Image /StartComponentCleanup /ResetBase」コマンドを実行してコンポーネントストアのクリーンアップを開始。進まないように見えても我慢

 コンポーネントストアには、品質更新プログラムのアンインストールを可能にするため、品質更新プログラムで置き換えられた古いバージョンの歴代のバイナリが格納されています。「C:\WindowsやC:\Windows\System32」ディレクトリに配置されているバイナリは、コンポーネントストアに存在する最新バージョンのバイナリに対するハードリンクとなっており、品質更新プログラムをアンインストールすると、そのハードリンクが古いバージョンに付け替わります。

 “コンポーネントストアのクリーンアップ”は、品質更新プログラムで置き換えられた古いバージョンのバイナリを削除することであり(「/ResetBase」は全て削除)、その影響で品質更新プログラムをアンインストールできなくなります。

 コンポーネントストアのクリーンアップについては、以下の日本語および英語ドキュメントで説明されています。ただし、日本語ドキュメントは、ドキュメントプラットフォーム(msdn.microsoft.comからdocs.microsoft.comへの)移行の影響により、将来削除される可能性があります。移行先のドキュメントは現状、日本語化されていません。

 置き換えられたバイナリの数や、置き換えられた回数(品質更新プログラムの数)が増えていくと、コンポーネントストアのクリーンアップにかかる時間も当然のことですが増加します。仮想マシン環境やVHDブート環境など、ディスクのオーバーヘッドが大きい場合は、さらに尋常ではない時間がかかることがあります。

 結論から言うと、問題のWindows Server 2016では4時間以上かかり、1.5GB程度の領域を解放できました(画面3)。せっかくなので別の物理サーバでも実施したのですが、そちらは7時間以上かかりました。

画面3 画面3 4時間以上かかってようやく終了し、1.5GB程度の領域を解放することができた

 この違いの理由は定かではありませんが、過去にクリーンアップを実行したことがあるかないかが関係しているのかもしれません。また、「/ResetBase」を付けなければもう少し短縮できるかもしれませんが、時間を比較したわけではありません。実は、過去には仮想マシン環境で状態の保存と再開を繰り返しながら、数日かけて完了させ、約30GBの領域を解放したこともあります。

 DISMコマンドの実行中、1行目のインジケーターの10%、70.4%、100%、2行目の100%のところで完全にストップしているように見えました(前出の画面3)。数時間も変化がないと、ハングアップしていると誤解して中断([Ctrl]+[C]キーで)してしまう人もいるでしょう。

 しかし、その間も「C:\Windows\Logs\DISM\DISM.log」や「C:\Windows\Logs\CBS\CBS.log」には次々とログが書き込まれており、止まっていないことが分かります。Windows PowerShellを開いて次のコマンドラインを実行すれば、書き込まれている情報を確認できます(画面4)。

Get-Content -Path C:\Windows\Logs\DISM\DISM.log -tail 0 -wait
Get-Content -Path C:\Windows\Logs\CBS\CBS.log -tail 0 -wait

画面4 画面4 10%や70.4%、100%のところで止まっているように見えても、「CBS.log」には処理したパッケージの膨大な情報が次々と書き込まれている

 Windows Sysinternalsの「Process Monitor」(Procmon.exe)を利用すれば、「Tiwalker.exe」プロセスが「C:\Windows\Servicing\Packages」ディレクトリにある膨大なカタログファイル(.catおよび.mum)や、「HKLM\SOFTWARE\Microsoft\Windows\CurrentCersion\Component Bassed Servicing\Packages」レジストリを1つずつ処理し、最終段階で(2行目の100%に到達してから)1時間程度あるいは数時間かけて「C:\Windows\WinSxS」からバイナリを削除している様子を見ることができました。

 止まっているように見えても、止まっていないんです。数時間かければ進むことを信じ、我慢して待つしかありません。

 画面5は、バイナリ「gdi32.dll」に対応するコンポーネントストア内の歴代のバイナリを、DISMコマンド(「/ResetBase」付き)の実行前と実行後で比較したものです。「gdi32.dll」のハードリンクを確認するのに、Windows Sysinternalsの「FindLinks」ユーティリティーを使用していますが、Windowsの標準コマンドで「fsutil hardlink list <ファイルパス>」と実行することでも確認できます。

画面5 画面5 DISMコマンドによるクリーンアップを「/ResetBase」付きで実行すると、オリジナルと最新のバイナリの2つを残し、置き換えられたバイナリが全て削除された
       1|2 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。