
前回、 Raspberry Pi システム SD のバックアップイメージを検証してみたところ、ファイルシステムエラーが検出されました。日頃より何となく言われるままに付与していた dd の オプション を Raspberry Pi で使う SD カードを対象とする場合にフォーカスしてまとめました。
進捗表示
バッチ処理ではなく手動で操作する場合にあると便利な進行状況確認は、イメージ生成・復元どちらにおいてもpvをパイプで挟まず、ddに用意されている「status=progress」オプションでも可能です。
1 2 3 4 5 |
$ sudo dd bs=1M if=./airpi_sdd_ddrescued.img of=/dev/sdd conv=fsync status=progress 15925772288 bytes (16 GB, 15 GiB) copied, 1570 s, 10.1 MB/s ←ココが処理中進捗表示 15193+1 レコード入力 15194+0 レコード出力 15932063744 bytes (16 GB, 15 GiB) copied, 2153.55 s, 7.4 MB/s |
SDカードのイメージを生成する場合
ブロックサイズを大きく取れば短い時間で終わりますが、ファイルシステムに破損がある場合、データをうまく吸い上げることが出来ない可能性があることや、SDカードインターフェイス(カードリーダ含)の転送速度がボトルネックになり大した時間短縮にならないことからも、ブロックサイズは無指定デフォルト(512バイト)とし、さらに「conv=sync,noerror」を付与して、「より正しい」イメージを生成出来るように努めるのが良いようです。cronによるRaspberry Pi システムSDカードの定期バックアップは、次のように登録しました。
1 |
# dd if=/dev/mmcblk0 conv=sync,noerror | gzip -6 -c > /mnt/md6/backup/homePi2.img.gz |
イメージをSDカードに焼く場合
逆にダウンロードしたOSのイメージをSDカードに焼き込む場合は、ブロックサイズを大きく取っても問題無いと言う理解で良さそうです。Raspberry Pi 公式ドキュメントでも「bs=4M」を推奨として、懸念が有る場合は「bs=1M」がアドバイスされていました。
さらに、「conv=fsync」を付与していたり、dd後にはキャッシュを明示的に反映するために「sudo sync」してからSDカードを取り出すようにも、丁寧に述べられています。また、unzipからオンザフライで焼く方法もわざわざ解説してあるのは嬉しい限り。
以上より、イメージをSDカードへ焼く場合は、
1 |
$ sudo dd bs=4M if=2021-01-11-raspios-buster-armhf.img of=/dev/sdX status=progress conv=fsync |
解凍しながら焼く場合は、
1 |
$ unzip -p 2021-01-11-raspios-buster-armhf.zip | sudo dd of=/dev/sdX bs=4M conv=fsync |
7zアーカイブでは次の要領でパイプ渡しすることが出来ます。
1 2 3 4 5 |
$ 7z x ./DietPi_RPi-ARMv6-Buster.7z -so | sudo dd of=/dev/sdd bs=4M conv=fsync status=progress 1069614389 bytes (1.1 GB, 1020 MiB) copied, 77 s, 13.9 MB/s 255+2 レコード入力 255+2 レコード出力 1069614389 bytes (1.1 GB, 1020 MiB) copied, 209.938 s, 5.1 MB/s |
実際に実行してみると、2行目のddのステータスは途中で止まりますが(77sec)書き込みは続いていて、根気良く待っていると最終的な結果が出力されて焼き込みは終わります(209sec)。
オンザフライ圧縮時にpigzを使う
バックアップ時の容量を小さく収めたり、ネットワークストレージへの転送量を減らす為に、gzipにパイプ渡しすることが多いのですが、マルチコア対応版のpigzを使うことで高速化を望めるようです。
pigzに渡すことでどの程度速くなるのか、i7-2600K搭載のUbuntu18.04LTSデスクトップPCで比較試験してみました。USB2.0接続のカードリーダに挿した、volumio用microSDカード16GBのイメージを生成しながら圧縮してみましょう。まずはpigzのインストール。
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 |
$ sudo apt install pigz パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 以下のパッケージが新たにインストールされます: pigz アップグレード: 0 個、新規インストール: 1 個、削除: 0 個、保留: 1 個。 57.4 kB のアーカイブを取得する必要があります。 この操作後に追加で 259 kB のディスク容量が消費されます。 取得:1 http://archive.ubuntu.com/ubuntu bionic/universe amd64 pigz amd64 2.4-1 [57.4 kB] 57.4 kB を 1秒 で取得しました (49.6 kB/s) 以前に未選択のパッケージ pigz を選択しています。 (データベースを読み込んでいます ... 現在 565188 個のファイルとディレクトリがインストールされています。) .../archives/pigz_2.4-1_amd64.deb を展開する準備をしています ... pigz (2.4-1) を展開しています... pigz (2.4-1) を設定しています ... man-db (2.8.3-2ubuntu0.1) のトリガを処理しています ... $ pigz --help Usage: pigz [options] [files ...] will compress files in place, adding the suffix '.gz'. If no files are specified, stdin will be compressed to stdout. pigz does what gzip does, but spreads the work over multiple processors and cores when compressing. Options: -0 to -9, -11 Compression level (level 11, zopfli, is much slower) --fast, --best Compression levels 1 and 9 respectively -b, --blocksize mmm Set compression block size to mmmK (default 128K) -c, --stdout Write all processed output to stdout (won't delete) -d, --decompress Decompress the compressed input -f, --force Force overwrite, compress .gz, links, and to terminal -F --first Do iterations first, before block split for -11 -h, --help Display a help screen and quit -i, --independent Compress blocks independently for damage recovery -I, --iterations n Number of iterations for -11 optimization -J, --maxsplits n Maximum number of split blocks for -11 -k, --keep Do not delete original file after processing -K, --zip Compress to PKWare zip (.zip) single entry format -l, --list List the contents of the compressed input -L, --license Display the pigz license and quit -m, --no-time Do not store or restore mod time -M, --time Store or restore mod time -n, --no-name Do not store or restore file name or mod time -N, --name Store or restore file name and mod time -O --oneblock Do not split into smaller blocks for -11 -p, --processes n Allow up to n compression threads (default is the number of online processors, or 8 if unknown) -q, --quiet Print no messages, even on error -r, --recursive Process the contents of all subdirectories -R, --rsyncable Input-determined block locations for rsync -S, --suffix .sss Use suffix .sss instead of .gz (for compression) -t, --test Test the integrity of the compressed input -v, --verbose Provide more verbose output -V --version Show the version of pigz -Y --synchronous Force output file write to permanent storage -z, --zlib Compress to zlib (.zz) instead of gzip format -- All arguments after "--" are treated as files |
はじめはブロックサイズ指定せずに、gzipとpigzそれぞれに渡した場合を比較してみます。
1 2 3 4 5 6 7 8 9 10 11 |
$ sudo dd if=/dev/sdd conv=sync,noerror iflag=nocache oflag=nocache,dsync | pv | gzip -6 -c > ./volumioSD.img.gz 30318592+0 レコード入力B/s] [ <=> ] 30318592+0 レコード出力 15523119104 bytes (16 GB, 14 GiB) copied, 938.246 s, 16.5 MB/s 14.5GiB 0:15:40 [15.7MiB/s] [ <=> ] $ sudo dd if=/dev/sdd conv=sync,noerror iflag=nocache oflag=nocache,dsync | pv | pigz -6 -c > ./volumioSDpigz.img.gz 30318592+0 レコード入力B/s] [ <=> ] 30318592+0 レコード出力 15523119104 bytes (16 GB, 14 GiB) copied, 932.552 s, 16.6 MB/s 14.5GiB 0:15:34 [15.8MiB/s] [ <=> ] |
別段、高速でもない普通のUSBカードリーダから読み込むSDカードがボトルネックとなってしまい、マルチコアを活かせていません。次にブロックサイズを上げて同様に比較してみます。
1 2 3 4 5 6 7 8 9 10 11 |
$ sudo dd if=/dev/sdd bs=16M iflag=nocache oflag=nocache,dsync | pv | gzip -6 -c > ./volumioSD.img.gz 925+1 レコード入力5.8MiB/s] [ <=> ] 925+1 レコード出力 15523119104 bytes (16 GB, 14 GiB) copied, 1125.22 s, 13.8 MB/s 14.5GiB 0:18:47 [13.1MiB/s] [ <=> ] $ sudo dd if=/dev/sdd bs=16M iflag=nocache oflag=nocache,dsync | pv | pigz -6 -c > ./volumioSDpigz.img.gz 925+1 レコード入力5.6MiB/s] [ <=> ] 925+1 レコード出力 15523119104 bytes (16 GB, 14 GiB) copied, 982.425 s, 15.8 MB/s 14.5GiB 0:16:22 [15.1MiB/s] [ <=> ] |
こちらはわずかながらpigzの速さが、と言いたいところですが、Raspberry PiやSDカードと言った領域ではpigzは活かしきれないようです。SATAやUSB3.0の高速インターフェースで繋がるストレージを対象に今回のような試験をすると、pigzの速さを体感出来るようです。
障害のあるディスクにはddrescue
障害のあるディスクに対するddの方法を調べていた時に見付けたのがこのddrescue、UbuntuのGNU版ddrescueを使ってみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ sudo ddrescue -v /dev/sdd ./airpi_sdd_ddrescued.img GNU ddrescue 1.22 About to copy 15931 MBytes from '/dev/sdd' to './airpi_sdd_ddrescued.img' Starting positions: infile = 0 B, outfile = 0 B Copy block size: 128 sectors Initial skip size: 384 sectors Sector size: 512 Bytes ipos: 15931 MB, non-trimmed: 0 B, current rate: 2686 kB/s opos: 15931 MB, non-scraped: 0 B, average rate: 17701 kB/s non-tried: 0 B, bad-sector: 0 B, error rate: 0 B/s rescued: 15931 MB, bad areas: 0, run time: 14m 59s pct rescued: 100.00%, read errors: 0, remaining time: n/a time since last successful read: n/a Finished $ ls -l -rw-r--r-- 1 user user 2365444096 Feb 26 15:44 airpi.img -rw-r--r-- 1 root root 15931539456 Feb 26 16:42 airpi_sdd_ddrescued.img |
バッドセクタ、リードエラー等の異常検出無しで正常終了してしまいました。ループデバイスに登録して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 |
$ sudo losetup -f /dev/loop14 $ sudo partx -v -a ./airpi_sdd_ddrescued.img パーティション: none, ディスク: ./airpi_sdd_ddrescued.img, 下限: 0, 上限: 0 ループバックデバイスとして '/dev/loop14' を使用しようとしています /dev/loop14: パーティション情報のタイプ 'dos' を検出しました range recount: max partno=2, lower=0, upper=0 /dev/loop14: パーティション #1 を追加しました /dev/loop14: パーティション #2 を追加しました $ sudo fsck -fy -C0 /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 -C0 -t ext4 /dev/loop14p2 fsck from util-linux 2.31.1 e2fsck 1.44.1 (24-Mar-2018) Pass 1: Checking iノードs, blocks, and sizes Pass 2: Checking ディレクトリ structure Pass 3: Checking ディレクトリ connectivity Pass 4: Checking reference counts Pass 5: Checking グループ summary information /dev/loop14p2: 47464/969136 files (0.2% non-contiguous), 377371/3874176 blocks $ sudo partx -v -d /dev/loop14 パーティション: none, ディスク: /dev/loop14, 下限: 0, 上限: 0 /dev/loop14: パーティション #1 を削除しました /dev/loop14: パーティション #2 を削除しました $ sudo losetup -d /dev/loop14 |
ddで吸い上げた時は、同様にループデバイスからfsckチェック掛けるとエラーが検出されるのですが、ddrescueではノーエラー。もしや、とこのイメージを別のSDカードに焼いて起動させてみましたが、図1のカーネルパニックに変わりはありませんでした、別の要因が残存しているのかも知れません。
普段の定期バックアップもddからddrescueに置き換えた方が良いのではと思ったのですが、ddrescueでは標準出力が出来ません。これは欠点ではなくそもそもの手法がddと異なるからであり、それがrescueと銘打っている所以でもあります。平時のバッチ処理向けではなく、障害時の強力なレスキューツールと考えたほうが良さそうです。
ddrescueについての解説、障害時のレスキュー試行について次の記事が大変参考になりました。ddrescueにはGUIなどの周辺ツールもあるようなので、次回障害発生時に使ってみようと思います。