前書き

OSが入ったストレージをより小さな容量のストレージに移したくなったことありませんか?私はあります。

データが入ったストレージであれば、ファイル単位でコピーすることで(時間をかければ)解決する話なのですが、システムが入ってるとなるとファイルだけ移しても意味ないわけです。

dd コマンドは同一サイズのストレージに引っ越すときはこれ単体で完結するのですが、ストレージ容量が違うとなるとパーティション周りで厄介があります。

パーティションテーブルでは、一般的にストレージの容量情報も扱っており、ddはこれも全く同じデータとなります。そうなると、実際のストレージ容量とパーティションテーブルの管理情報に齟齬が出て、パーティションを正しく扱えなくなります。

今回、Debianが入った1TBのストレージを500GBのストレージに引っ越して、OSの起動まで確認します。パーティションテーブルはGPTです。意識する必要はないですが、DebianはLuksの上にbtrfsでインストールしています。

なお、一部の環境で使われている属性は引き継げずに破壊されるらしいです。

注意

前項の内容を理解できる人向けです。結果についてはすべて自己責任でお願いします。

作業

準備

オリジナル(コピー元)のストレージから不要なファイルを削除して、ストレージ使用量を減らしてください。

任意のOSをLive CDでブートします。私はいつもUbuntuを使用していますが、「GParted Live CD」なるものもあるようです。

コピー元のストレージのパーティションを縮小します。この作業には「GParted」が便利です。Luksで暗号化してあっても、これを解除してパーティションの操作ができます。(もちろん、カギは必要です。)

前方から容量の小さな(コピー先)ストレージの容量の範囲までにしてください。なるべくパーティションを前方に詰めることで、ddコマンドの所要時間を短くできます。

作業が終わったら、GPartedを終了しておいてください。

クローン

ddコマンドでコピー元からコピー先へコピーします。

この時、ifオプションとofオプションは絶対に間違わないでください。(間違えるとデータを失います。)

私がいつも使っているオプションを載せておきます。

dd if=/dev/sdX of=/dev/sdX bs=4k status=progress

不良セクタがある場合は、以下のオプションを指定することで、読めない領域をスキップできます。ただし、読めなかった領域にあったデータ(ファイルなど)は破損します。

conv=sync,noerror

必要な範囲は、実際にパーティションが存在する領域だけですので、countオプションでコピーするブロック数を指定するか、必要な範囲をコピーしきったらCtrl + Cで中断できます。

私の場合、countオプションは指定せず、ddコマンド実行中は完全に席を外していたので、戻ったころには最後の領域までコピーされていました。この場合、コピー先の容量の上限でddコマンドが終了します。

パーティションテーブルの修復(再構築)

GPTを修復します。

gdisk /dev/sdX
x
v
e
m
w
y

x : プロフェッショナルモードに移行
v : gptの整合性を確認
e : 修正
m : 通常モード
w : 変更内容を書き込み
y : 書き込み実施の確認

btrfsを使用している私の環境では、GPartedでエラーが出るようになります。

コンピューターの電源を切り、コピー元のストレージを取り外してください。(作業者自らの混乱防止と、同じUUIDを持つストレージが2つ存在していることによるユーティリティーソフトでの識別不良防止の為)

パーティションの拡張

コピー先のストレージでパーティションを拡張します。

動作確認

コピー先のストレージでOSが起動できることを確認します。

参考資料

https://kappaseijin.hatenablog.com/entry/20160924/1474683913