[Raspberry Pi 3]ディスクイメージを作ってバックアップする
Raspberry Piのバックアップとして、イメージディスクを作る。
単純にバックアップを取るだけだと、SDカード内の空き領域を含めた無駄にでかいイメージファイルになってしまうので、ここでは圧縮したイメージディスクを作る。
2種類の方法を紹介。
パーティションを縮小してからバックアップを取る方法
圧縮というか、パーティションを縮めてしまえばイメージディスクのサイズが小さくなるでしょう、という考え。
主にUbuntu(Linux)を使う。
パーティションを縮小
まずGPartedでSDカードのパーティションを縮小する。
空き領域をギリギリまで削ってしまうと縮小に失敗するので、少し余裕を持たせて縮小させる。
僕の場合、8.2GBまでしか縮小できないところを、8.5GBで縮小しようとしたらエラーが発生した。
9GBで成功した。
更に言うと、Raspbianでやろうとしたら失敗して、Ubuntuだとうまくいった。
shrink file system 00:00:00 ( ERROR )
resize2fs -p /dev/sda2 8704000K
resize2fs 1.42.12 (29-Aug-2014)
resize2fs: New size smaller than minimum (2291995)
ddコマンドでイメージディスクを作る
UbuntuでもMacでもできる。
Ubuntu
デバイス名を調べる。
1 2 3 4 5 6 7 8 9 10 11 12 | $ sudo fdisk -l 〜略〜 Disk /dev/sdf: 29 GiB, 31117541376 bytes, 60776448 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: 0xa62ddb9c デバイス 起動 Start 最後から セクタ Size Id タイプ /dev/sdf1 8192 92159 83968 41M c W95 FAT32 (LBA) /dev/sdf2 92160 18524159 18432000 8.8G 83 Linux |
今回は/dev/sdfだとわかったので、以下のコマンドでパーティションサイズを調べる。
1 2 3 4 5 6 7 8 9 10 11 | $ sudo fdisk -l /dev/sdf Disk /dev/sdf: 29 GiB, 31117541376 bytes, 60776448 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: 0xa62ddb9c デバイス 起動 Start 最後から セクタ Size Id タイプ /dev/sdf1 8192 92159 83968 41M c W95 FAT32 (LBA) /dev/sdf2 92160 18524159 18432000 8.8G 83 Linux |
/dev/sdf2の「最後から」の数値が最終セクタ番号になるらしい。
ということで、その値に+1した値を指定して、以下のコマンドを走らせるらしい。
1 | $ sudo dd if=/dev/sdf of=~/rpi.img count=18524160 status=progress |
また、status=progressをつけることで進捗が見られるようになる。
ちなみに、うちの環境だとこれで転送速度が20[MB/s]くらいになる。
Mac
SDカードがどのデバイスかを確認。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | $ diskutil list /dev/disk0 (internal, physical): #: TYPE NAME SIZE IDENTIFIER 0: GUID_partition_scheme *251.0 GB disk0 1: EFI EFI 209.7 MB disk0s1 2: Apple_APFS Container disk1 250.8 GB disk0s2 /dev/disk1 (synthesized): #: TYPE NAME SIZE IDENTIFIER 0: APFS Container Scheme - +250.8 GB disk1 Physical Store disk0s2 1: APFS Volume Macintosh HD 201.3 GB disk1s1 2: APFS Volume Preboot 60.4 MB disk1s2 3: APFS Volume Recovery 1.5 GB disk1s3 4: APFS Volume VM 3.2 GB disk1s4 /dev/disk2 (internal, physical): #: TYPE NAME SIZE IDENTIFIER 0: FDisk_partition_scheme *31.1 GB disk2 1: Windows_FAT_32 boot 43.0 MB disk2s1 2: Linux 9.4 GB disk2s2 |
番号がわかったら、それを元に以下のコマンドを走らせる。
1 2 3 4 5 6 7 8 9 10 | $ sudo fdisk /dev/disk2 Disk: /dev/disk2 geometry: 3783/255/63 [60776448 sectors] Signature: 0xAA55 Starting Ending #: id cyl hd sec - cyl hd sec [ start - size] ------------------------------------------------------------------------ 1: 0C 0 130 3 - 5 187 54 [ 8192 - 83968] Win95 FAT32L 2: 83 416 0 1 - 1023 254 63 [ 92160 - 18432000] Linux files* 3: 00 0 0 0 - 0 0 0 [ 0 - 0] unused 4: 00 0 0 0 - 0 0 0 [ 0 - 0] unused |
2番目のstart+size(=18524160)が欲しいバックアップのサイズになるので、この値を指定してddコマンドを走らせる。
今回の場合、SDカードはdisk2だったので、それを指定して「rpi.img」という名前のイメージディスクを作る。
注意すべき事として、この時指定するデバイス名は「rdisk2」のように、先頭にrを足すこと。その方が早い。
2019/08/04追記: bsオプションも使えば転送速度を上げられる。
1 | $ sudo dd if=/dev/rdisk2 of=~/rpi.img count=18524160 bs=1m |
ちなみにCtrl+Tを押すことで、コピーの途中経過を知ることができる。
転送速度は1[MB/s]くらい。めちゃくちゃ遅い。
Ubuntuを持っているのであれば、Ubuntuでddコマンドを走らせて、それをUSBメモリでMacに移し替えるのがいいかも。
2019/08/04追記: bsオプションを使うことで60[MB/s]くらいまで上げられた。
SDカード全体のイメージファイルを作ってから圧縮する方法
圧縮には、Raspberry Piを使う。
ちなみにこの方法はRaspbian限定なので注意。
イメージファイルを作る
イメージファイルの作成はPCで行う。
デバイス名を調べる方法は上の項を見てほしいが、コピーするコマンドは以下のようになる。
今回はSDカード全体をコピーするのでcountオプションを使う必要がなく、bsオプションで転送速度を上げることができる。
2019/08/04追記: countオプションを使っていてもbsオプションで転送速度を上げられるっぽい。
Ubuntu
1 | $ sudo dd if=/dev/sdf of=~/rpi.img bs=1000000 status=progress |
転送速度は20[MB/s]くらい。
Ubuntuではあんまり違いが出ない。
Mac
1 | $ sudo dd if=/dev/rdisk2 of=~/rpi.img bs=1m |
転送速度が60[MB/s]くらいまで跳ね上がる。
Raspberry Piに接続
そしたら、生成したイメージファイルと下のPerlスクリプトを外付けHDDとかに入れて、Raspberry Piに接続する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #!/usr/bin/perl use utf8; use 5.010; use strict; #use autodie; use warnings; #use diagnostics; my $who = `whoami`; if ($who !~ /root/) { print "This should be run as root or with the sudo command.\n"; exit 1; } if (!$ARGV[0]) { print "No image file given.\n"; exit 1; } my $image = $ARGV[0]; if ($image !~ /^\//) { print "Please enter full path to image file.\n"; exit 1; } if (! -e $image) { print "$image does not exist.\n"; exit 1; } my @name = split (/\//, $image); print "\n$name[(scalar @name) - 1]:\n"; print "=" x (length ($name[(scalar @name) - 1]) + 1) . "\n"; my $info = `parted -m $image unit B print | grep ext4`; (my $num, my $start, my $old, my $dummy) = split (':', $info, 4); chop $start; chop $old; printf "Old size - %d MB (%1.2f GB)\n", int ($old / 1048576), ($old / 1073741824); my $loopback = `losetup -f --show -o $start $image`; chop $loopback; `e2fsck -p -f $loopback`; if ($? != 0) { print "There was an error in the file system that can't be automatically fixed... aborting.\n"; `losetup -d $loopback`; exit 1; } $info = `resize2fs -P $loopback 2>&1`; ($dummy, my $size) = split (': ', $info, 2); chop $size; $size = $size + 1024; `sudo resize2fs -p $loopback $size 2>&1`; sleep 1; `losetup -d $loopback`; $size = ($size * 4096) + $start; `parted $image rm $num`; `parted -s $image unit B mkpart primary $start $size`; $size = $size + 58720257; printf "New size - %d MB (%1.2f GB)\n", int ($size / 1048576), ($size / 1073741824); `truncate -s $size $image`; my $diff = $old - $size; printf "Image file was reduced by %d MB (%1.2f GB)\n", int ($diff / 1048576), ($diff / 1073741824); exit 0; |
ちなみに、Macの外付けHDDを接続した場合、フォーマットの違いで読み取り専用になってしまうので、以下のようにして書き込みもできるような形でマウントし直す。
1 2 3 | $ sudo apt-get install hfsprogs $ sudo umount /media/pi/Untitled $ sudo mount -t hfsplus -o force,rw /dev/sda2 /media/pi/Untitled |
圧縮する
Raspberry Piを起動したらターミナルを開き、resizeimage.plのあるディレクトリに移動して、以下のコマンドを実行。
1 2 | $ cd /media/pi/Untitled/ $ sudo perl ./resizeimage.pl /media/pi/Untitled/rpi.img |
これで圧縮されたimgファイルが作成されるはずだ。
場合によっては「/dev/loop0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.」といったようなエラーが出てしまうが、その時はなんとかしないといけない。
まだ解決法が見つかっていないので、ここはあとで追記する。
/dev/loop0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.というエラーが出た場合ですが、下記を実行した所、imgのスリム化が出来ました。
コマンドを実行
losetup /dev/loop0 イメージへのパス
kpartx -av /dev/loop0
以下にブロックデバイスとして、imgファイル内のパーティションがマウントされる。
/dev/mapper/loop0p1
/dev/mapper/loop0p2
コマンドを実行
fsck /dev/mapper/loop0p2
ループデバイスをアンマウント
kpartx -d /dev/loop0
losetup -d /dev/loop0
ご報告まで。