Raspberry Pi の SDカードを ”ddコマンド” でバックアップ

Raspberry Pi の SDカードの内容を ”ddコマンド” を使用して全てバックアップする手順を記述します。ただし、SDカードの記録容量は製品毎に微妙に異なる場合があるため、バックアップを違うSDカードに復元する場合にも考慮した手順にしたいと思います。

記載する手順は、バックアップ対象のSDカードが下記の状態を例としています。
・OS=Raspbian ※イメージファイルから作成(NOOBS未使用)
・SDカードの記録容量=16GByte
・Raspberry PiからSDカードを取り外した状態でバックアップ
バックアップ作業もRaspberry Piを使用して行います。(バックアップ対象とは異なるSDカードでbootしたRaspbian環境を使用)

1. バックアップ対象のSDカード内の情報を確認

Raspbianをイメージファイルを使用してインストールした場合、SDカード内に2つのパーティションが作成されます。1つ目はRaspberry Piのboot時に必要となるファイルが格納された、FATのファイルシステム。2つ目は、Raspbianの”/”が格納された、EXT4のファイルシステムになります。

2つ目のEXT4ファイルシステムのパーティションは、Raspbianインストール直後の初回reboot時に、SDカードの容量いっぱいまで拡張されています。
バックアップ対象のSDカードを、USB SDカードリーダ/ライタにセットしてRaspberry Piに接続し(/dev/sda で認識しているとします)、fdiskコマンドで確認します。

# fdisk /dev/sda

Welcome to fdisk (util-linux 2.29.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): p
Disk /dev/sda: 14.7 GiB, 15722348544 bytes, 30707712 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xab206736

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1        8192    96663    88472 43.2M  c W95 FAT32 (LBA)
/dev/sda2       98304 30707711 30609408 14.6G 83 Linux

上の例では、SDカード内に”30707712”セクタあり、2つ目のパーティション”/dev/sda2”が、SDカード内いっぱいに拡張されているのが確認できます。(End=”30707711”となっているのは、セクタ”0”からカウントするため、”-1”した値になっています)

2. EXT4(2つ目)パーティションを縮小する

SDカード製品毎の差で、微妙に記録容量が小さいSDカードにもリストアできる様に、あらかじめEXT4ファイルシステムが入っている2つ目のパーティションを縮小(14.6G→14.5G)し、SDカード内に未使用領域を作成し余裕をもたせます。

まず、ファイルシステムのチェックを実行します。

# e2fsck -f /dev/sda2
e2fsck 1.43.4 (31-Jan-2017)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
rootfs: 39402/924768 files (0.1% non-contiguous), 368006/3826176 blocks

その後、ファイルシステムのサイズを一時的に小さめに変更します。(最終の値ではありません。)

# resize2fs /dev/sda2 14G
resize2fs 1.43.4 (31-Jan-2017)
Resizing the filesystem on /dev/sda2 to 3670016 (4k) blocks.
The filesystem on /dev/sda2 is now 3670016 (4k) blocks long.

ファイルシステムの入るパーティションのサイズを変更(14.6G→14.5G)します。
操作的には、一度パーティションを削除し、新しいサイズ(14.5G)のパーティションを作成しなおすことになります。

# fdisk /dev/sda
Welcome to fdisk (util-linux 2.29.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): p
Disk /dev/sda: 14.7 GiB, 15722348544 bytes, 30707712 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xab206736

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1        8192    96663    88472 43.2M  c W95 FAT32 (LBA)
/dev/sda2       98304 30707711 30609408 14.6G 83 Linux

Command (m for help): d
Partition number (1,2, default 2): 2

Partition 2 has been deleted.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (2048-30707711, default 2048): 98304
Last sector, +sectors or +size{K,M,G,T,P} (98304-30707711, default 30707711): +14.5G

Created a new partition 2 of type 'Linux' and of size 14.5 GiB.
Partition #2 contains a ext4 signature.

Do you want to remove the signature? [Y]es/[N]o: N

Command (m for help): p

Disk /dev/sda: 14.7 GiB, 15722348544 bytes, 30707712 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xab206736

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1        8192    96663    88472 43.2M  c W95 FAT32 (LBA)
/dev/sda2       98304 30482431 30384128 14.5G 83 Linux

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

新しいパーティションのサイズ(14.5G)に合わせて、一時的に縮小していたファイルシステムのサイズを再拡張します。

# resize2fs /dev/sda2
resize2fs 1.43.4 (31-Jan-2017)
Resizing the filesystem on /dev/sda2 to 3798016 (4k) blocks.
The filesystem on /dev/sda2 is now 3798016 (4k) blocks long.

3. 修正したSDカードでの動作確認

修正したSDカードを使用して、Raspberry Piが正常にbootし、Raspbianが起動することを確認します。

4. ”ddコマンド” でサイズ指定してバックアップ

動作確認が終了したバックアップ対象のSDカードを、再度USB SDカードリーダ/ライタにセットしてRaspberry Piに接続します。
”ddコマンド” でのバックアップサイズは、ブロックサイズ”bs”と、カウント数”count”のオプション設定で決まります。
今回、ブロックサイズは”bs=16M” (16,777,216Byte)とします。
パーティションサイズ修正後の”/dev/sda2”の最終セクタはEnd=”30482431”となっていました。1セクタ=512Byteなので、SDカードの先頭からバックアップが必要なカウント数は次の様に求めます。
(30482431+1)*512=15,607,005,184Byte (←ddコマンドでバックアック必要な、最低Byte数)
15,607,005,184/16,777,216=930.25 (←ddコマンドで”bs=16M”指定時の最低カウント数)
930.25≒932 (←指定するカウント数、少数点以下を切り上げ、余裕をもたせました。)

ブロックサイズ”bs=16M”、カウント数”count=932”を指定した時にバックアップされる、最終セクタ値を確認してみます。
16,777,216*932=15,636,365,312Byte
15,636,365,312/512=30539776セクタ数
30539776-1=30539775 (←バックアップされる最終セクタ値)

上記の最終セクタ値が、パーティションのEnd=”30482431”より大きく、SDカードの全体セクタ数=”30707712”より小さいことを確認し、”ddコマンド” でのバックアップを行います。
以下は、出力に直接圧縮をかけ、ファイル出力した例になります。

# dd if=/dev/sda bs=16M count=932 | gzip -c > sd_dd_backup.gz
932+0 レコード入力
932+0 レコード出力
15636365312 bytes (16 GB, 15 GiB) copied, 2600.3 s, 6.0 MB/s

※バックアップしたSDカードは、RASPBIAN STRETCH LITEインストール直後のものだったため、出力された圧縮ファイルサイズは約1.1Gbyteでした。

※上記の手順で、”ddコマンド” が長時間終了しない場合は、バックアップ対象のSDカード内に、読取り不可能な部分がある可能性が考えられます。

5. ”ddコマンド” でバックアップをSDカードに復元する場合

復元先のSDカードは、”ddコマンド” バックアップ時のセクタ数=”30539776”より大きいものが必要になります。

# gunzip -c sd_dd_backup.gz | dd bs=16M of=/dev/sda
0+315899 レコード入力
0+315899 レコード出力
15636365312 bytes (16 GB, 15 GiB) copied, 1824.07 s, 8.6 MB/s

以上で完了です。