RaspberryPiのmicroSDカードをバックアップ/復元する方法にはいくつか方法があります。
しかしながら Windows や Mac で行う場合、ツールをインストールしたり、イメージの中身が読み書きできなかったりで敷居が高いです。
また、Linuxで行ったとしてもLinuxデスクトップではオートマウントが悪さをしてうっかりするとイメージ書き込みが思うようにできなかったりします。
また、例えば32GBytesのSDカードについて、実際には4GBytesぐらいしか使って無かった場合、
32GBytesをバックアップするのもかさばるし書き込み時間がかかって仕方がないですね。
また、32GBytesを32GBytesにコピーしようとしても、微妙にサイズが違って収まらなかったりします。その場合でも実害が出るとは必ずしも限りませんが、やっぱり気持ち悪いですね。
ここでは、RaspberryPiを使ってコンパクトに確実にバックアップや復元をする方法を紹介します。
今回の方法
特徴
- バックアップ、復元は ZIP 圧縮/展開しながら行う
- 速い! 2分でコピー(Raspbian buster ベースの1.6G使用時を復元の場合)。
- その代わりバックアップには手間がかかる
- ディスクイメージもZIP圧縮でコンパクト
概要
ここでは、RaspberryPiを使ってRaspberryPiのバックアップや復元を行う方法を紹介します。
残念ながら動作途中の自分自身のバックアップではなく、別のSDカードを使って起動し、ターゲットのSDカードをバックアップします。
また、完全にヘッドレスで行います。sshとかでログインして作業する方法。GUIを使う方法は、またの機会に。
必要なもの
- RaspberrtPi
- 操作用SDカード
- USB SDカードリーダライタ
- バックアップ元SDカード
- 保管用のUSBメモリなど
- 復元先SDカード
手順
シュリンク
- RaspberryPiを操作用SDカードで起動します
- バックアップ元SDカードをUSBリーダで接続、サイズをシュリンク
バックアップ
- RaspberryPiを操作用SDカードで起動します
- バックアップします
- シュリンクしたファイルシステムを拡張
復元
- RaspberryPiを操作用SDカードで起動します
- 復元
- シュリンクしたファイルシステムを拡張
シュリンク
まず、RaspberryPiを操作用SDカードで起動します
分析
dmesg -w
としてから、バックアップ元のmicroSDカードをUSBカードリーダを使ってUSBポートに刺します。
[sda] Attached SCSI removable disk
と出るので、 sdaデバイスであることがわかります。
Ctrl+Cで止めて、
sudo fdisk -l /dev/sda
として分析します
Disk /dev/sda: 29.5 GiB, 31652315136 bytes, 61820928 sectors
Disk model: SD Card Reader
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: 0x6c586e13
Device Boot Start End Sectors Size Id Type
/dev/sda1 8192 532479 524288 256M c W95 FAT32 (LBA)
/dev/sda2 532480 61820927 61288448 29.2G 83 Linux
と出ています。/dev/sda2 の Start の 532480、End の 61820927 の値が重要です。後で使うことを覚えておきましょう。
ファイルシステム使用量を確認
$ sudo mount /dev/sda2 /mnt
一旦マウントして、
pi@raspberrypi:~ $ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 6.9G 1.3G 5.4G 19% /
devtmpfs 459M 0 459M 0% /dev
tmpfs 464M 0 464M 0% /dev/shm
tmpfs 464M 12M 452M 3% /run
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 464M 0 464M 0% /sys/fs/cgroup
tmpfs 93M 0 93M 0% /run/user/1000
/dev/sda2 29G 1.6G 26G 6% /mnt
として、使用量を見ます。/dev/sda2 は 1.6GBtres 使用しています。
pi@raspberrypi:~ $ sudo umount /dev/sda2
としてアンマウントしておきます。
resize2fs
resize2fs をそのまま起動したら
pi@raspberrypi:~ $ sudo resize2fs /dev/sda2
resize2fs 1.44.5 (15-Dec-2018)
Please run 'e2fsck -f /dev/sda2' first.
と出ました。先にe2fsckをかけておきます。
pi@raspberrypi:~ $ e2fsck -f /dev/sda2
e2fsck 1.44.5 (15-Dec-2018)
e2fsck: Permission denied while trying to open /dev/sda2
You must have r/w access to the filesystem or be root
pi@raspberrypi:~ $ sudo e2fsck -f /dev/sda2
e2fsck 1.44.5 (15-Dec-2018)
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: 51665/1883232 files (0.2% non-contiguous), 538568/7661056 blocks
では、もう一度。
pi@raspberrypi:~ $ sudo resize2fs /dev/sda2
resize2fs 1.44.5 (15-Dec-2018)
The filesystem is already 7661056 (4k) blocks long. Nothing to do!
何も起こりませんでした。今度は縮小後のファイルシステムサイズを指定していきます。先程使用量は1.6Gでした。小さめから1G,2G,3G・・・と順に試してしていきます。
pi@raspberrypi:~ $ sudo resize2fs /dev/sda2 1G
resize2fs 1.44.5 (15-Dec-2018)
resize2fs: New size smaller than minimum (642567)
pi@raspberrypi:~ $ sudo resize2fs /dev/sda2 2G
resize2fs 1.44.5 (15-Dec-2018)
resize2fs: New size smaller than minimum (642567)
pi@raspberrypi:~ $ sudo resize2fs /dev/sda2 3G
resize2fs 1.44.5 (15-Dec-2018)
Resizing the filesystem on /dev/sda2 to 786432 (4k) blocks.
The filesystem on /dev/sda2 is now 786432 (4k) blocks long.
3GBytesになりました。もうちょっと詰めたいな〜と思い、2.9Gとすると・・・
pi@raspberrypi:~ $ sudo resize2fs /dev/sda2 2.9G
resize2fs 1.44.5 (15-Dec-2018)
resize2fs: Invalid new size: 2.9G
小数指定はダメでした。今度は2100M,2200M,2400M,2500M と増やしていきます。
pi@raspberrypi:~ $ sudo resize2fs /dev/sda2 2400M
resize2fs 1.44.5 (15-Dec-2018)
resize2fs: New size smaller than minimum (628817)
pi@raspberrypi:~ $ sudo resize2fs /dev/sda2 2500M
resize2fs 1.44.5 (15-Dec-2018)
Resizing the filesystem on /dev/sda2 to 640000 (4k) blocks.
The filesystem on /dev/sda2 is now 640000 (4k) blocks long.
2500Mで通りました。このサイズでOKとしました。4kブロックが640000とありますね。この数字も覚えておきます。
なお、元々1.6Gしか使っていないのにそれまで詰めることができないのは恐らくディスクのフラグメント的な何かかな〜と思います。もしこれが著しくひどいようならフラグメント解消をする必要が出てきますが、今回はこのまま進めます。
fdisk
次に、fdisk コマンドを使います。
pi@raspberrypi:~ $ sudo fdisk /dev/sda
Welcome to fdisk (util-linux 2.33.1).
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: 29.5 GiB, 31652315136 bytes, 61820928 sectors
Disk model: SD Card Reader
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: 0x6c586e13
Device Boot Start End Sectors Size Id Type
/dev/sda1 8192 532479 524288 256M c W95 FAT32 (LBA)
/dev/sda2 532480 61820927 61288448 29.2G 83 Linux
/dev/sda2 パーティションを削除し、新たなパーティーションを e2fsck で設定したファイスリステムサイズに合わせて作成します
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):
First sector (2048-61820927, default 2048): 532480
ここの値は先程確認した値を入力します
Last sector, +/-sectors or +/-size{K,M,G,T,P} (532480-61820927, default 61820927): +`expr 640000 '*' 8`
数字の前に+
をつけて、セクタ数でパーティションを指定するようにします。
次に、e2fsck で作成したファイルシステムサイズ 640000 にあわせてパラメータを指定します。
セクタサイズが512Bytesでした。4096ブロックの640000を512Bytesセクタに換算すると8を掛けることになります。
計算にexprとしようとしましたが、ここではexprは使えないのでした。とりあえず別に計算した値を入力します。
Last sector, +/-sectors or +/-size{K,M,G,T,P} (532480-61820927, default 61820927): +5120000
Created a new partition 2 of type 'Linux' and of size 2.5 GiB.
Partition #2 contains a ext4 signature.
Do you want to remove the signature? [Y]es/[N]o: y
The signature will be removed by a write command.
うまくいったかな・・・確認してみましょう
Command (m for help): p
Disk /dev/sda: 29.5 GiB, 31652315136 bytes, 61820928 sectors
Disk model: SD Card Reader
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: 0x6c586e13
Device Boot Start End Sectors Size Id Type
/dev/sda1 8192 532479 524288 256M c W95 FAT32 (LBA)
/dev/sda2 532480 5652480 5120001 2.5G 83 Linux
Filesystem/RAID signature on partition 2 will be wiped.
ここの、Sectors
の値が意図したものかどうか照合して下さい
うーん? 1つずれてしまいました。そうですね、終了セクタは1つ引き算をしないといけません。
今作ったパーティションは消してしまいましょう。
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):
First sector (2048-61820927, default 2048): 532480
Last sector, +/-sectors or +/-size{K,M,G,T,P} (532480-61820927, default 61820927): +5119999
Created a new partition 2 of type 'Linux' and of size 2.5 GiB.
Partition #2 contains a ext4 signature.
Do you want to remove the signature? [Y]es/[N]o: y
The signature will be removed by a write command.
Command (m for help): p
Disk /dev/sda: 29.5 GiB, 31652315136 bytes, 61820928 sectors
Disk model: SD Card Reader
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: 0x6c586e13
Device Boot Start End Sectors Size Id Type
/dev/sda1 8192 532479 524288 256M c W95 FAT32 (LBA)
/dev/sda2 532480 5652479 5120000 2.5G 83 Linux
Filesystem/RAID signature on partition 2 will be wiped.
OKです。書き込みます。
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
さて、このままマウントしようとしたら
pi@raspberrypi:~ $ sudo mount /dev/sda2 /mnt
mount: /mnt: wrong fs type, bad option, bad superblock on /dev/sda2, missing codepage or helper program, or other error.
エラーになりました。
もう一度e2fsck
pi@raspberrypi:~ $ sudo e2fsck -f /dev/sda2
e2fsck 1.44.5 (15-Dec-2018)
ext2fs_open2: Bad magic number in super-block
e2fsck: Superblock invalid, trying backup blocks...
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: ***** FILE SYSTEM WAS MODIFIED *****
rootfs: 51665/160960 files (0.2% non-contiguous), 429904/640000 blocks
したらうまくいきました。
マウントして使用容量を確認します。
pi@raspberrypi:~ $ sudo mount /dev/sda2 /mnt
pi@raspberrypi:~ $ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 6.9G 1.3G 5.4G 19% /
devtmpfs 459M 0 459M 0% /dev
tmpfs 464M 0 464M 0% /dev/shm
tmpfs 464M 12M 452M 3% /run
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 464M 0 464M 0% /sys/fs/cgroup
tmpfs 93M 0 93M 0% /run/user/1000
/dev/sda2 2.4G 1.6G 704M 70% /mnt
pi@raspberrypi:~ $ sudo umount /dev/sda2
使用は1.6Gですが、2.4Gのパーティションになりました。
バックアップ
準備
あらかじめ、zip コマンドをインストールしておきます。
pi@raspberrypi:~ $ sudo apt install zip
バックアップ元を接続
dmesg -w としてUSBカードリーダに入れたSDカードを差し込みます。
[sda] Attached SCSI removable disk
と出るので、 sdaデバイスであることがわかります。
バックアップ先を接続
dmesg -w としてUSBメモリを入れます。
[ 7037.585895] sd 1:0:0:0: [sdb] Attached SCSI removable disk
と出るので /dev/sdb であることがわかります。
dmesg を Ctrl+Cで止めておきます。
pi@raspberrypi:~ $ sudo fdisk -l /dev/sdb
Disk /dev/sdb: 57.3 GiB, 61505273856 bytes, 120127488 sectors
Disk model: Ultra Fit
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: 0xe4af68c6
Device Boot Start End Sectors Size Id Type
/dev/sdb1 * 2048 65538047 65536000 31.3G 7 HPFS/NTFS/exFAT
として、USBメモリであることを確認してから
pi@raspberrypi:~ $ sudo mount /dev/sdb1 /mnt
とマウントします。中身を確認するには
pi@raspberrypi:~ $ ls /mnt
'System Volume Information' bootmgr hunsn lenovoL540.png sources upgrade
autorun.inf bootmgr.efi j4d214ww.exe produkey-x64.zip support
boot efi j4r205ww_764_864.exe setup.exe tb_free.exe
とします。
ソース、ディスティネーション指定
書き込み時の、指定の間違いで事故が起こことを防止するために、
pi@raspberrypi:~ $ export SOURCE=/dev/sda
pi@raspberrypi:~ $ export DIST=/mnt/raspbian-FABLIB-20191221.img.zip
とします。DISTのファイル名は適当に。
バックアップ実行
$ sudo dd if=$SOURCE bs=512 count=5652480 | zip > $DIST.zip
数字は先程 fdisk で確認した End のあたいをしていしまs
とすると書き込み終了まで何も出てこず、最後に
adding: -5652480+0 records in
5652480+0 records out
2894069760 bytes (2.9 GB, 2.7 GiB) copied, 671.977 s, 4.3 MB/s
(deflated 67%)
と出てきます。10分強かかっていますね。
バックアップイメージ名を設定する
このままだと内部に書き込んだものはファイル名が - となるので、名前を付け直します。
printf "@ -\n@=raspbian-FABLIB-20191221.img\n" | zipnote -w $DIST.zip
完成したバックアップファイル
-rwxrwxrwx 1 root root 907M Dec 21 05:40 /mnt/raspbian-FABLIB-20191221.img.zip
となりました。かなり小さくなってお得。
取り出し
syncしてumountして取り出します
pi@raspberrypi:~ $ sync;sync;sync
pi@raspberrypi:~ $ sudo umount /mnt
復元
スーパーユーザになる
sudo ごしの操作はちょっと煩雑になるので以下のようにしてスーパーユーザになってしまいます。
pi@raspberrypi:~ $ sudo bash
バックアップイメージの入っているUSBリーダメモリを接続
dmesg -w として バックアップイメージの入っているUSBリーダメモリを接続します。
[ 9463.830093] sd 0:0:0:0: [sda] Attached SCSI removable disk
と出るので、 /dev/sdaデバイスであることがわかります。
fdiskで確認してみます。
root@raspberrypi:/home/pi# fdisk -l /dev/sda
Disk /dev/sda: 57.3 GiB, 61505273856 bytes, 120127488 sectors
Disk model: Ultra Fit
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: 0xe4af68c6
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 65538047 65536000 31.3G 7 HPFS/NTFS/exFAT
間違いないですね。
USBメモリをマウント
root@raspberrypi:/home/pi# mount /dev/sda1 /mnt
バックアップイメージを確認します。
root@raspberrypi:/home/pi# ls /mnt
'System Volume Information' bootmgr.efi j4r205ww_764_864.exe setup.exe upgrade
autorun.inf efi lenovoL540.png sources
boot hunsn produkey-x64.zip support
bootmgr j4d214ww.exe raspbian-FABLIB-20191221.img.zip tb_free.exe
raspbian-FABLIB-20191221.img.zip があるのがわかりますね。
コピー先を接続
sdカードをUSBカードリーダーに入れてUSBインターフェースに刺します。
[ 9641.771349] sd 1:0:0:0: [sdb] Attached SCSI removable disk
と出るので、 /dev/sdbデバイスであることがわかります。
コピー元、コピー先指定
root@raspberrypi:/home/pi# export SOURCE=/mnt/raspbian-FABLIB-20191221.img.zip
root@raspberrypi:/home/pi# export DIST=/dev/sdb
復元
以下のコマンドで展開しながら書き込みます
root@raspberrypi:/home/pi# unzip -p $SOURCE | dd bs=4k of=$DIST status=progress
以下のようになりました。
706560+0 records in
706560+0 records out
2894069760 bytes (2.9 GB, 2.7 GiB) copied, 134.109 s, 21.6 MB/s
速い! SandiskのClass10を使いましたが2分ちょっとで終わりましたね。
syncして取り外し
root@raspberrypi:/home/pi# sync;sync;sync
root@raspberrypi:/home/pi# umount /mnt
シュリンクしたファイルシステムを拡張
シュリンクした状態では以下のようになっています。
pi@raspberrypi:~ $ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 2.4G 1.6G 704M 70% /
devtmpfs 433M 0 433M 0% /dev
tmpfs 438M 0 438M 0% /dev/shm
tmpfs 438M 5.9M 432M 2% /run
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 438M 0 438M 0% /sys/fs/cgroup
/dev/mmcblk0p1 253M 52M 201M 21% /boot
tmpfs 88M 0 88M 0% /run/user/1000
sudo raspi-configで、Advancedを選び、最大容量までパーティションを増やすことができます。
32GのSDカードを使って拡張した後の状態:
pi@raspberrypi:~ $ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 29G 1.6G 27G 6% /
devtmpfs 433M 0 433M 0% /dev
tmpfs 438M 0 438M 0% /dev/shm
tmpfs 438M 5.9M 432M 2% /run
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 438M 0 438M 0% /sys/fs/cgroup
/dev/mmcblk0p1 253M 52M 201M 21% /boot
tmpfs 88M 0 88M 0% /run/user/1000
pi@raspberrypi:~ $
最後に
今回は、動作途中の自分自身のバックアップではなく、別のSDカードを使って起動し、ターゲットのSDカードをバックアップしました。
動作途中の自分自身のバックアップはライブバックアップとかホットバックアップと呼ばれる方法になります。
これらについてはいくつかツールがあるようですが、また今度・・・