2024/03/26
KAICHO: s_naray[at]yahoo[dot]co[dot]jp
※SPAM防止のため捻ってある

DiskClone 〜 ディスク複製スクリプト for SystemRescue

■はじめに

本文書は、 SystemRescue +partclone ベースで、ディスク全体を簡単に複製するスクリプト DiskClone について述べる。

細けぇこたぁいいから現物見せろ!という人はこちらから。短いPerlスクリプト。 使い方なんかは本ページの下の方に。

なお、本文書では複製元HDD/SSDを「元ディスク」、複製先HDD/SSDを「先ディスク」と呼称する。

■免責事項

本ツールは大変に危険で、指定方法を間違うと容易にディスク内容を破損してしまう。 正しく指定したとしても、万一バグがあったりするとやっぱり破壊されてしまうかも。 ので、何かあっても私は絶対責任を取らない、絶対にだ! そして少なくとも元ディスク・先ディスクの指定を誤らないようご注意を。 あと作業前にバックアップを取ろう必ず。オレタチのヤクソクだ!

■OSの(特にWindowsの)システム移行って面倒じゃん?

OSのシステム移行の時(例えばマシン更新とかHDD/SSD買い換えたとか)、みんなどうしてる? OS再インストールして、アプリも再インストールして、色々設定し直して…とかやってる? マジで?ワォ。そんなの面倒じゃん!ディスクそのまままるっとコピーして、前と全く同じ環境が即座に使えるようになったら楽じゃん!

…というのが、スクリプトを作ろうと思った切っ掛けだった。 世の中には既にそういうツールは結構ある。代表的なのは EaseUS Disk Copyで、 これはよくできてるし有償版も安いから買っちゃえる人は買えばいいと思う。 あとClonezillaはフリーよね。 とはいえ、こういうツールはどれも有償だったり汎用性が低かったりパーティションの切り方があんま賢くなかったり元より小さいデバイスには複製できなかったり使用対象SSDがメーカーで制限されていたりヤケに使い方が難しかったりなど、色々制約が多い。

欲しい機能は単純で、WindowsのOSディスクを「イイカンジに」複製するだけ!それだけ! なのにそれがない! だったら、貧乏エンジニアは自分でできることは自分でやるかー、ということで、 そういうのを自作してみることにしたわけで。

■特徴

仕組みは簡単で、ざっくり言えば「1USB Linuxで起動して 元ディスク上の全パーティションを先ディスクにコピーする」だけ。以上!

コピーに用いるツールとして、 partcloneが(そしてこれが SystemRescueにインストールされているのが)福音だった(Clonezillaもインストール されてるけどね)。 コレ使えば、ファイルシステム上の「使用してる分だけ」をコピーできるので、 ディスク全体を複製するよりとてつもなく時間短縮になるからだ。

ついでにちょっとがんばって、パーティションの位置を前詰めにするとかWindowsに合わせて変更するとか、そういう機能を追加している。

長所は以下のようなカンジ。

■使い方

使い方は「まぁまぁ簡単」。初心者でもイケるくらい手間が減るよう色々考えた、つもり。 簡単な手順は以下の通り。

  1. SystemRescue USBを用意し、この上にDiskClone.plを配置
  2. 元ディスクと先ディスクをPCに接続
  3. SystemRescue USBでPCを起動
  4. 元ディスクと先ディスクのデバイス名を確認
  5. DiskClone.plを実行
  6. SystemRescueを終了して元ディスクを取り外す

以下順番に説明する。

SystemRescue USBを用意し、この上にDiskClone.plを配置

SystemRescueは いわゆる1CD Linux(≒1USB Linux)。2GBもあれば格納できるので、 一つ作って手元に置いておくと便利。リンクページの[Download] から iso ファイルが入手できる。 Rufusを使えば、 USBブートするようUSBに焼き込める。

USBブートできる SystemRescue メディアができたら、それのトップディレクトリに DiskClone.plをコピーしておく。

元ディスクと先ディスクをPCに接続

PCの電源を落とし、元ディスク、先ディスク(勝手に消去するので内容はなんでもいい)をPCに接続する。SystemRescueが認識するのであれば、接続はSATAだろうがNVMeだろうがUSBだろうがなんでもいい。とにかく接続する。

SystemRescue USBでPCを起動

SystemRescue USBをPCに挿し、F12やDELやらを押しながらPCを起動して、 起動先としてSystemRescue USBを選択する。 うっかり元ディスクや先ディスクから起動してしまうと、 わけわからん状態になることがあるので要注意。

SystemRescueの起動メニューでは(既に選択されている)一番上でそのまま起動すれば、Linux のコマンドラインになるはずだ。

元ディスクと先ディスクのデバイス名を確認

SystemRescue 上のデバイス名を確認する。SATAかUSB接続なら /dev/sda〜/dev/sdz、 NVMe接続なら /dev/nvme#n#(#は数値)になっているはず。どれがどれかわからない場合は、 parted を使って

# parted /dev/デバイス名 -s print

とかやれば、デバイスのサイズなどの情報と(あれば)パーティション情報が表示される。 それらから元ディスク・先ディスクを把握する。

あと "cat /sys/block/デバイス名/device/model" で表示されるモデル名を参考にすれば わかるかもしれない。

DiskClone.plを実行

USBメモリ上に配置した DiskClone.pl は、/mnt/archiso/bootmnt 以下に配置されている。ので、それを実行する。

# cd /mnt/archiso/bootmnt
# perl -w DiskClone.pl <元ディスク> <先ディスク>

各種オプションの意味は以下の通り。全ての操作は先ディスクに対してのみ実行され、元ディスクは全く変更しない。オプションを何もつけないと、元ディスク・先ディスクのパーティション情報は全く同一になる。ので、その時先ディスクが元ディスクより小さくパーティションが収まらない場合はエラーになる。収めるなら --compact か --winlocate でなんとかなるかもしれない。

オプションDOS PT使用可?GPT使用可? 意味指定例
--helpヘルプを表示する-
--test元ディスク・先ディスクをチェックのみし、実際には何もしない-
--compact×全パーティションを隙間なく前詰めする-
--winlocate×パーティションをWindowsの標準的な順番に配置する。Windowsのシステムディスクを複製するときに指定すると吉。EFI→Reserved→Data(=C:)→回復パーティションの順になり、また回復パーティションはディスク末尾に配置される。ただし、パーティション番号は元のまま-
--reorder×パーティション番号を、ディスク先頭からふり直す。--winlocateでパーティション番号が昇順にならなくなるのがイヤな場合に使用する-
--winonly×Windowsに関連するパーティションのみをコピーする。具体的には、パーティションの型のGUIDのうち、WikiのWindowsのパーティションGUID(5種)とEFIパーティションのみを対象とする。それ以外のパーティションは無視する-
--verbose実行時に詳細情報を表示する-
--partonly先ディスクにパーティションを切るが、元ディスクからパーティションの内容はコピーしない-
--forcedd全パーティションコピー時、partclone.fs ではなくddを使い完全コピーする-
--only=パーティションリスト×元ディスクのコピー対象パーティションを限定する。複数指定する場合は , で区切る--only=/dev/sda1,/dev/sda3
--except=パーティションリスト×元ディスクのコピーしないパーティションを指定する。--onlyの逆--except=/dev/nvme0n1p3,/dev/nvme0n1p5
--partdata=ファイルかなり上級者向け。事前に sfdisk -d <元ディスク> で取得した情報を手作業で修正したファイルを、先ディスクのパーティションデータとして使用する。DOS PTの場合は同ファイル中の start= 以外の情報を修正してはならない。GPTの場合、start=の変更に加え、不要なパーティションをファイル中で削除したり、パーティション番号(ex. /dev/sda2の2の部分)を変更してもよい。
このオプションが指定された場合、--compactや--winlocateなど他のオプションは無視する。
--partdata=sfdiskdump.txt

パーティションの物理位置やパーティション番号を変更しても、多くの場合は問題ない。 のだが、OSブートに関わるディスクの場合、問題があるかもしれない。 例えば懐かしのLILOなどのブートシステムでは、 ファイルの位置を物理的に覚えているので、位置を移動するとOSが起動しなくなる。 OS 起動に失敗する場合は、オプションなしで複製するか 複製後に自前で修正する必要がある。Windowsの場合は修正手順を後述する。

実行時の出力は以下の通り。以下は、Windows 11 がインストールされた /dev/sdb を /dev/sda にコピーしている例。

[root@sysrescue /mnt/archiso/bootmnt]# perl -w DiskClone.pl --winlocate --reorder /dev/sdb /dev/sda
Disk cloner ver 2024-03-25-0
Getting source device information...
Configuring destination device...
Relocating partitions for Windows...

Destination disk(/dev/sda) will be changed to:
label: gpt
label-id: B12EB2BD-A4D5-494C-9592-B65AA55612D2
device: /dev/sda
unit: sectors
first-lba: 34
last-lba: 62914526
sector-size: 512

/dev/sda1 : start=2048, size=204800, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=A48F7A33-6D89-44E0-B7A9-87F326D30103, name="EFI system partition", attrs="GUID:63"
/dev/sda2 : start=206848, size=32768, type=E3C9E316-0B5C-4DB8-817D-F92DF00215AE, uuid=CFCB1BC4-30D0-4DBA-994A-97802632F221, name="Microsoft reserved partition", attrs="GUID:63"
/dev/sda3 : start=239616, size=53229568, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, uuid=C3E2882C-495A-41D8-805E-661979D82E39, name="Basic data partition"
/dev/sda4 : start=61251576, size=1658880, type=DE94BBA4-06D1-4D40-A16A-BFD50179D6AC, uuid=46436C60-7CBA-4750-B07A-9EE3351363E6, attrs="RequiredPartition GUID:63"

ALL PARTITIONS on /dev/sda will be REMOVEd. OK? [y/n] y
Copying MBR...
Applying destination device information...
Copying partitions...
    Copying fat32 from /dev/sdb1 to /dev/sda1...
    Cloning partition from /dev/sdb2 to /dev/sda2...
    Copying ntfs from /dev/sdb3 to /dev/sda3...
    Copying ntfs from /dev/sdb4 to /dev/sda4...
Succeeded.
[root@sysrescue /run/archiso/bootmnt]#

内部的には、概ね以下のような順番で処理を実行している。

  1. 最初に両デバイスから情報を入手
  2. オプションに応じて 先ディスク に設定するパーティション情報を出力
  3. このまま進めてよいか y/n で聞いてくるので y を入力
  4. 先ディスクのパーティションを作成
  5. パーティションごとに複製

最後に "Succeeded." と表示されたら、複製は正常終了しているはず。エラーが出たら… --verbose オプションつけて詳細確認してみるとか?

SystemRescueを終了して元ディスクを取り外す

SystemRescue は "shutdown -h now" で終了する。

PC停止後、元ディスクを取り外す。これ大事。 DiskClone.plは、ディスクGUID、パーティションタイプやパーティションGUIDなども 全て複製する。そのため、元ディスク・先ディスク両方をPCに接続したままOSを起動すると、本来重複しないはずのGUIDが重複して存在することに混乱したOSが起動しなくなるか最悪両方のディスクを破壊してしまうかもしれない。 従って、DiskClone.pl実行後の再起動前に、必ず元ディスク・先ディスクどちらかを 取り外す必要がある。

SystemRescue USB も取り外した後は、普通にPCを起動すればよい。 OS入りのディスクなら、ブートローダもコピーされているので、 何事もなく OS が起動するはず。

■制限

現在の本ツールには、以下のような制限がある。

■Windowsが起動しない場合の復旧方法

EFIブートの場合、EFIパーティション上のブート情報が壊れているか古いか誤っていることが原因。なので、これを更新すればよい。

簡単解決するには、まずWindowsインストールDVD/USBで起動して、 「スタートアップの修復」とやらを選択して起動情報を修復してみる。 Microsoftから色々方法が紹介されているので見てみるとよろし。

それでも修復できない場合は、なんとかして bcdboot コマンドを実行する。 いやいやWindows自体起動しないのだからコマンドなんて実行無理じゃん! と思うかもしれないが、Windowsの回復ツールかインストールDVD/USBで起動して、 コマンドプロンプトを表示させることでなんとかなる。 Windows インストールDVD/USBなら以下のように操作すると、 コマンドプロンプトが表示できる。

  1. WindowsインストールDVD/USBから起動
  2. 最初の画面では[次へ]
  3. 「コンピューターを修復する」を選択
  4. 「トラブルシューティング」を選択
  5. 「コマンドプロンプト」を選択

その後、コマンドプロンプト上で以下のように操作する。 これで、EFIパーティション に C:\Windows の起動情報が書き込まれた。

X:\windows\system32> diskpart

DISKPART> select disk 0
DISKPART> list partition
(EFIパーティションのパーティション番号を確認)
DISKPART> select partition EFIパーティションのパーティション番号
DISKPART> assign letter=S
DISKPART> exit

X:\windows\system32> bcdboot C:\windows /s S:

もしどうしてもうまくいかない場合は、EFIパーティション上に不要なファイルが残っているためかもしれない。ので、一度EFIパーティションをfat32でフォーマットした後に再度試してみるとよい。bcdboot コマンドは EFIパーティション上に必要なファイルを再配置してくれるため、フォーマットされていても問題ない。

■Windows回復パーティションを認識しない場合の復旧方法

Windowsの回復パーティション、削除したり認識できなくなっちゃうと、 復旧するにはOS再インストールするしかないという話もあるが、 なんとかできなくもない。

今、回復パーティションが認識されているかどうかは、 管理者権限で起動した cmd.exe 内での reagentc コマンドで確認できる。 「Windows RE の状態」が Enabled であれば認識している。 Disabled だと認識できていない。

C:\windows\system32> reagentc /info
Windows 回復環境 (Windows RE) およびシステム リセット構成
情報:

    Windows RE の状態:         Enabled
    Windows RE の場所:         \\?\GLOBALROOT\device\harddisk0\partition4\Recovery\WindowsRE
    ブート構成データ (BCD) ID: ########-####-####-####-############
    回復イメージの場所:
    回復イメージ インデックス: 0
    カスタム イメージの場所:
    カスタム イメージ インデックス: 0

REAGENTC.EXE: 操作は成功しました。

最初にやることは、これをEnabled に変更可能かどうか試すこと。/enable オプションをつけて実行するだけ。 ただ、これで「操作は成功しました」って言われても信じてはいけない。 今一度 reagentc /info を実行して、確かに Enabled になっているかどうかを確認すること。

C:\windows\system32> reagentc /enable
C:\windows\system32> reagentc /info

Enabled にならない場合は、 ディスクの管理ツールで回復パーティションが存在するかどうかを確認する。 以下の赤丸パーティションが存在するならよし、なければ、自分で作成する必要がある。

ない場合に自分作る時、Winre.wim というファイルが必要になることに注意。 このファイルがどこにも見当たらないことが多い。 C:\windows\system32\Recovery\ 以下に存在すればラッキー、そうでなければ、 「どっか別のマシンにインストールしてあるWindowの回復パーティションから Winre.wim を引っ張り出す」という手順が必要。面倒。 引っ張り出す時は、そのどっかのマシン上の管理者権限の cmd.exe 上で、以下のように操作する。

C:\windows\system32> diskpart

DISKPART> select disk 0
DISKPART> list partition
(回復パーティションのパーティション番号を確認)
DISKPART> select partition 回復パーティションのパーティション番号
DISKPART> assign letter=R
DISKPART> exit

C:\windows\system32> xcopy /h R:\Recovery\WindowsRE\Winre.wim コピー先

その後、回復パーティションを作成したいマシン上で、 管理者権限の cmd.exe 上で以下を実行する。 回復パーティション作成用に 1GB の空き領域が必要なことに注意。

C:\windows\system32> diskpart

DISKPART> select disk 0
DISKPART> create partition primary size=1024
DISKPART> format quick fs=ntfs label="Recovery Partition"
DISKPART> assign letter=R
DISKPART> set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"
DISKPART> gpt attributes=0x8000000000000001
DISKPART> exit

C:\windows\system32> mkdir R:\Recovery
C:\windows\system32> mkdir R:\Recovery\WindowsRE
C:\windows\system32> xcopy /h (コピーしてきた)Winre.wim R:\Recovery\WindowsRE
C:\windows\system32> reagentc /setreimage /path R:\Recovery\WindowsRE
C:\windows\system32> reagentc /enable
C:\windows\system32> reagentc /info

これで回復パーティションが Enabled になったはず。 この時点では R ドライブが見えているが、OS 再起動すれば見えなくなるので放置でよろし。 Enabled にならない場合は…色々やってみてくれぃ…。例えば、 C:/Windows/System32/Recovery/*.xml を削除してから reagentc /setreimage ... するといいとか。

回復パーティションって別になくてもOSは動くし特に不具合はないし復旧が必要ならWindowsインストールDVD/USBがあればなんとかなる。のだが、 先日「回復パーティションがないと一部のWindows Updateが失敗し続ける」という 問題を確認したので、まぁやっぱり作っておいた方がいいかなとは思う。

■その他

何かあったらメールなりでお知らせください。

■おわりに

このくらいのプログラムって世界に落ちてないかしらと思ったけれど、あんまりなさそう。 やっぱり普通の人はSSDメーカーとかが提供してる移行ツール使うかOS再インストールしちゃうのかなー。