
以前記事にした通り、 Raspberry Pi の稼働しているシステムSDカードを dd により、定期的に別のストレージへディスクイメージとしてバックアップしているのですが、その中のファイルシステムに異常は無いのか。物理的にレストアすることなく、 ループデバイス を使って検証する方法をまとめます。
Raspberry Pi のシステムが入ったSDカードをネットワーク内のNASへsshプロトコルを通じ、圧縮イメージとしてバックアップする要領は、おおよそ次の通りです(NASとのssh疎通は予め証明書を交わしてパスワードレス)。
1 |
dd if=/dev/mmcblk0 | gzip -6 | ssh USER@IP_ADDR dd of=/mnt/md0/backup/$HOSTNAME.img.gz |
この作業が異常終了しない限りは中身のファイルシステムも正常に違いない、と身勝手な理解をしていましたが、はっきりさせたくて今回の検証に至りました。尚、本記事中の作業は全て、Ubuntu 18.04 にて行なっています。
1 2 3 4 5 6 7 8 |
$ uname -a Linux 4.15.0-136-generic #140-Ubuntu SMP Thu Jan 28 05:20:47 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.5 LTS Release: 18.04 Codename: bionic |
イメージファイル内のパーティション構成を確認
イメージファイルのパーティション構成は、定番のfdiskの他、 partx でも確認することが出来ます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ sudo fdisk -lu airpi.img ディスク airpi.img: 2.2 GiB, 2365444096 バイト, 4620008 セクタ 単位: セクタ (1 * 512 = 512 バイト) セクタサイズ (論理 / 物理): 512 バイト / 512 バイト I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト ディスクラベルのタイプ: dos ディスク識別子: 0xba2edfb9 デバイス 起動 開始位置 最後から セクタ サイズ Id タイプ airpi.img1 8192 122879 114688 56M c W95 FAT32 (LBA) airpi.img2 122880 31116287 30993408 14.8G 83 Linux $ sudo partx -s airpi.img NR START END SECTORS SIZE NAME UUID 1 8192 122879 114688 56M ba2edfb9-01 2 122880 31116287 30993408 14.8G ba2edfb9-02 |
単一パーティションにより構成されるイメージファイルの場合は、イメージマウンタでマウント出来ますが、複数パーティションには対応していないので、その場合はターミナルから操作することになります。
オフセットマウント
例えば2番めのパーティションをマウントさせたい場合、 fdisk でそのパーティションの開始セクタ位置とセクタサイズから算出されるオフセット量をオプションに入れて次のように実行します。
1 2 3 4 5 6 7 8 9 10 11 12 |
$ sudo fdisk -lu airpi.img ディスク airpi.img: 2.2 GiB, 2365444096 バイト, 4620008 セクタ 単位: セクタ (1 * 512 = 512 バイト) セクタサイズ (論理 / 物理): 512 バイト / 512 バイト I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト ディスクラベルのタイプ: dos ディスク識別子: 0xba2edfb9 デバイス 起動 開始位置 最後から セクタ サイズ Id タイプ airpi.img1 8192 122879 114688 56M c W95 FAT32 (LBA) airpi.img2 122880 31116287 30993408 14.8G 83 Linux $ sudo mount -o loop,offset=$((122880 * 512)) ./airpi.img /mnt/part |
しかしながら今回は、 fsck によるファイルシステム検証を行いたいので、マウントしてしまってはむしろ不都合。こんな時に使うのがループデバイスなのだそうです。
現在のループデバイスの一覧
まず、 losetup -l で現在のループデバイスの利用状況を確認してみます。Snapが多用しているようです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ losetup -l NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC /dev/loop1 0 0 1 1 /var/lib/snapd/snaps/gtk-common-themes_1513.snap 0 512 /dev/loop8 0 0 1 1 /var/lib/snapd/snaps/core_10823.snap 0 512 /dev/loop6 0 0 1 1 /var/lib/snapd/snaps/core_10583.snap 0 512 /dev/loop13 0 0 1 1 /var/lib/snapd/snaps/gtk2-common-themes_13.snap 0 512 /dev/loop4 0 0 1 1 /var/lib/snapd/snaps/gtk2-common-themes_9.snap 0 512 /dev/loop11 0 0 1 1 /var/lib/snapd/snaps/communitheme_1768.snap 0 512 /dev/loop2 0 0 1 1 /var/lib/snapd/snaps/gtk-common-themes_1514.snap 0 512 /dev/loop0 0 0 1 1 /var/lib/snapd/snaps/communitheme_1987.snap 0 512 /dev/loop9 0 0 1 1 /var/lib/snapd/snaps/pdftk_9.snap 0 512 /dev/loop7 0 0 1 1 /var/lib/snapd/snaps/chromium_1479.snap 0 512 /dev/loop5 0 0 1 1 /var/lib/snapd/snaps/chromium_1497.snap 0 512 /dev/loop12 0 0 1 1 /var/lib/snapd/snaps/gnome-3-28-1804_145.snap 0 512 /dev/loop3 0 0 1 1 /var/lib/snapd/snaps/core18_1944.snap 0 512 /dev/loop10 0 0 1 1 /var/lib/snapd/snaps/core18_1988.snap 0 512 |
次の空いているループデバイス名の取得
そして、次に割り当てられる予定のループデバイス名を確認します。
1 2 |
$ sudo losetup -f /dev/loop14 |
ディスクイメージをループデバイスに新規登録
partx -a コマンドでイメージファイルをループデバイスに登録します。その後再びループデバイス一覧を取得すると、確かに loop14 として登録されています。
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 |
$ sudo partx -v -a ./airpi.img パーティション: none, ディスク: ./airpi.img, 下限: 0, 上限: 0 ループバックデバイスとして '/dev/loop14' を使用しようとしています /dev/loop14: パーティション情報のタイプ 'dos' を検出しました range recount: max partno=2, lower=0, upper=0 /dev/loop14: パーティション #1 を追加しました /dev/loop14: パーティション #2 を追加しました $ losetup -l NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC /dev/loop1 0 0 1 1 /var/lib/snapd/snaps/gtk-common-themes_1513.snap 0 512 /dev/loop8 0 0 1 1 /var/lib/snapd/snaps/core_10823.snap 0 512 /dev/loop6 0 0 1 1 /var/lib/snapd/snaps/core_10583.snap 0 512 /dev/loop13 0 0 1 1 /var/lib/snapd/snaps/gtk2-common-themes_13.snap 0 512 /dev/loop4 0 0 1 1 /var/lib/snapd/snaps/gtk2-common-themes_9.snap 0 512 /dev/loop11 0 0 1 1 /var/lib/snapd/snaps/communitheme_1768.snap 0 512 /dev/loop2 0 0 1 1 /var/lib/snapd/snaps/gtk-common-themes_1514.snap 0 512 /dev/loop0 0 0 1 1 /var/lib/snapd/snaps/communitheme_1987.snap 0 512 /dev/loop9 0 0 1 1 /var/lib/snapd/snaps/pdftk_9.snap 0 512 /dev/loop7 0 0 1 1 /var/lib/snapd/snaps/chromium_1479.snap 0 512 /dev/loop14 0 0 0 0 /str500/conv3/airpi.img 0 512 /dev/loop5 0 0 1 1 /var/lib/snapd/snaps/chromium_1497.snap 0 512 /dev/loop12 0 0 1 1 /var/lib/snapd/snaps/gnome-3-28-1804_145.snap 0 512 /dev/loop3 0 0 1 1 /var/lib/snapd/snaps/core18_1944.snap 0 512 /dev/loop10 0 0 1 1 /var/lib/snapd/snaps/core18_1988.snap 0 512 |
ループデバイスのパーティション構成を確認
登録されたループデバイスに対して fdisk を実行すると、その中の各パーティションに割り振られたデバイス名を確認することが出来ます。
1 2 3 4 5 6 7 8 9 10 |
$ sudo fdisk -lu /dev/loop14 ディスク /dev/loop14: 2.2 GiB, 2365444096 バイト, 4620008 セクタ 単位: セクタ (1 * 512 = 512 バイト) セクタサイズ (論理 / 物理): 512 バイト / 512 バイト I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト ディスクラベルのタイプ: dos ディスク識別子: 0xba2edfb9 デバイス 起動 開始位置 最後から セクタ サイズ Id タイプ /dev/loop14p1 8192 122879 114688 56M c W95 FAT32 (LBA) /dev/loop14p2 122880 31116287 30993408 14.8G 83 Linux |
ループデバイスに対するファイルシステムチェック
早速、各々のパーティションに対してfsckをかけてみました。まず /boot が入っているFAT32パーティションのエラーは修復されました。しかしながら、ルートが入っているパーティションのエラーは深刻で、実際にはオプションを色々変えながら何度か fsck を走らせましたが、同じエラーが挙がり修復不能です。
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 |
$ ls -l -rw-r--r-- 1 user user 2365444096 Feb 25 12:51 airpi.img $ sudo fsck -fy /dev/loop14p1 fsck from util-linux 2.31.1 fsck.fat 4.1 (2017-01-24) 0x25: Dirty bit is set. Fs was not properly unmounted and some data may be corrupt. Automatically removing dirty bit. Performing changes. /dev/loop14p1: 119 files, 2658/7161 clusters $ sudo fsck /dev/loop14p1 fsck from util-linux 2.31.1 fsck.fat 4.1 (2017-01-24) /dev/loop14p1: 119 files, 2658/7161 clusters $ sudo fsck -fy -t ext4 /dev/loop14p2 fsck from util-linux 2.31.1 e2fsck 1.44.1 (24-Mar-2018) /dev/loop14p2: recovering journal fsck.ext4: Unknown code ____ 251 while recovering journal of /dev/loop14p2 Pass 1: Checking iノードs, blocks, and sizes Error reading block 1048608 (入力/出力エラーです) while getting next inode from scan. Ignore error? yes Force rewrite? yes - 略 - Error writing file system info: 入力/出力エラーです /dev/loop14p2: ***** ファイルシステムは変更されました ***** $ ls -l -rw-r--r-- 1 user user 2365444096 Feb 26 15:10 airpi.img |
ループデバイスのマウント
もしもループデバイスの中身を覗きたい時には、通常のブロックデバイス同様にマウントします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$ sudo mount -t ext4 /dev/loop14p2 /mnt/part $ mount | grep /dev/loop /dev/loop14p2 on /mnt/part type ext4 (rw,relatime,data=ordered) $ ls -l /mnt/part drwxr-xr-x 2 root root 4096 Oct 7 2016 bin drwxr-xr-x 2 root root 4096 Sep 24 2015 boot drwxr-xr-x 2 root root 4096 Jan 7 2015 dev drwxr-xr-x 99 root root 4096 May 11 2020 etc drwxr-xr-x 3 root root 4096 Sep 24 2015 home drwxr-xr-x 19 root root 4096 Oct 11 2016 lib drwx------ 2 root root 16384 Sep 24 2015 lost+found drwxr-xr-x 2 root root 4096 Sep 24 2015 media drwxr-xr-x 2 root root 4096 Sep 24 2015 mnt drwxr-xr-x 3 root root 4096 Nov 19 2015 opt drwxr-xr-x 2 root root 4096 Jan 7 2015 proc drwx------ 3 root root 4096 Mar 2 2018 root drwxr-xr-x 5 root root 4096 Sep 24 2015 run drwxr-xr-x 2 root root 12288 Feb 20 2020 sbin drwxr-xr-x 2 root root 4096 Sep 24 2015 srv drwxr-xr-x 2 root root 4096 Apr 12 2015 sys drwxr-xr-x 10 root root 4096 Sep 24 2015 usr drwxr-xr-x 11 root root 4096 Feb 20 2020 var $ sudo umount /dev/loop14p2 |
コマンドでのマウントの他、GUIベースではDisksユーティリティでも物理ディスクと同じように認識されますので、そこからマウントすることも可能です。
ループデバイス登録解除
partx コマンドでループデバイスからイメージファイルを取り外します。あくまでまだ取り外しただけなので、 losetup で次の空き番号をチェックすると未だ loop15 と言われます。
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 |
$ sudo partx -v -d /dev/loop14 パーティション: none, ディスク: /dev/loop14, 下限: 0, 上限: 0 /dev/loop14: パーティション #1 を削除しました /dev/loop14: パーティション #2 を削除しました $ sudo losetup -f /dev/loop15 $ ls -l /dev/loop* crw-rw---- 1 root disk 10, 237 Feb 26 07:58 /dev/loop-control brw-rw---- 1 root disk 7, 0 Feb 26 07:58 /dev/loop0 brw-rw---- 1 root disk 7, 1 Feb 26 07:58 /dev/loop1 brw-rw---- 1 root disk 7, 10 Feb 26 07:58 /dev/loop10 brw-rw---- 1 root disk 7, 11 Feb 26 07:58 /dev/loop11 brw-rw---- 1 root disk 7, 12 Feb 26 07:58 /dev/loop12 brw-rw---- 1 root disk 7, 13 Feb 26 07:58 /dev/loop13 brw-rw---- 1 root disk 7, 14 Feb 26 14:27 /dev/loop14 brw-rw---- 1 root disk 7, 2 Feb 26 07:58 /dev/loop2 brw-rw---- 1 root disk 7, 3 Feb 26 07:58 /dev/loop3 brw-rw---- 1 root disk 7, 4 Feb 26 07:58 /dev/loop4 brw-rw---- 1 root disk 7, 5 Feb 26 07:58 /dev/loop5 brw-rw---- 1 root disk 7, 6 Feb 26 07:58 /dev/loop6 brw-rw---- 1 root disk 7, 7 Feb 26 07:58 /dev/loop7 brw-rw---- 1 root disk 7, 8 Feb 26 07:58 /dev/loop8 brw-rw---- 1 root disk 7, 9 Feb 26 07:58 /dev/loop9 |
/dev に残っている loop14 を直接 rm コマンドなどで無理やり消去することは出来てしまうものの、 losetup との整合性が取れなくなってしまい、その解消には再起動を要してしまうので止めておきましょう。
不要なループデバイスの空箱を消去
losetup コマンドで不要になったループデバイスを消すと、 loop14 が再び使用可能になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ sudo losetup -d /dev/loop14 $ losetup -l NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC /dev/loop1 0 0 1 1 /var/lib/snapd/snaps/gtk-common-themes_1513.snap 0 512 /dev/loop8 0 0 1 1 /var/lib/snapd/snaps/core_10823.snap 0 512 /dev/loop6 0 0 1 1 /var/lib/snapd/snaps/core_10583.snap 0 512 /dev/loop13 0 0 1 1 /var/lib/snapd/snaps/gtk2-common-themes_13.snap 0 512 /dev/loop4 0 0 1 1 /var/lib/snapd/snaps/gtk2-common-themes_9.snap 0 512 /dev/loop11 0 0 1 1 /var/lib/snapd/snaps/communitheme_1768.snap 0 512 /dev/loop2 0 0 1 1 /var/lib/snapd/snaps/gtk-common-themes_1514.snap 0 512 /dev/loop0 0 0 1 1 /var/lib/snapd/snaps/communitheme_1987.snap 0 512 /dev/loop9 0 0 1 1 /var/lib/snapd/snaps/pdftk_9.snap 0 512 /dev/loop7 0 0 1 1 /var/lib/snapd/snaps/chromium_1479.snap 0 512 /dev/loop5 0 0 1 1 /var/lib/snapd/snaps/chromium_1497.snap 0 512 /dev/loop12 0 0 1 1 /var/lib/snapd/snaps/gnome-3-28-1804_145.snap 0 512 /dev/loop3 0 0 1 1 /var/lib/snapd/snaps/core18_1944.snap 0 512 /dev/loop10 0 0 1 1 /var/lib/snapd/snaps/core18_1988.snap 0 512 $ losetup -f /dev/loop14 |
dd で生成したディスクイメージをループデバイスに登録して検証する一連の作業は以上です。せっかく定期的に作っているバックアップが使い物にならないことほど、虚しいことはありません。ループデバイスを応用してバックアップイメージの検証もバッチ処理で自動化出来れば、障害の早期対処に役立つことでしょう。