シングルボードコンピュータ(SBC)のマスターディスクの作り方

【趣旨】

RaspberryPi, OrangePi, BanaPi などで、複数台を構築する際に利用。

〇 利点

  •  HDD保管領域の容量節約
  •  イメージをSDカードへ展開する時間の短縮

〇 欠点

  • 面倒くさい
  • HDD保管領域や作業時間が十分にに取れる場合は、
    マスターとなるSDカードを空のSDカードへディスクコピーしたほうが簡単

    ※ 滅多に行わないので備忘として残す

【作業環境】

手頃なLinuxOS端末 -- 母艦OSと呼称。
※ SDカードで使用されているファイルシステムは、サポート可能である事。
※ FAT, ext4など

【情報収集】

  • SDカードのOSはArmbian
  • SDカードの総容量は32GB
  • Loaderはu-bootが使用されている。
    母艦OSにSDカード(USB変換アダプタなどで)を認識。認識デバイス /dev/sdiと仮定。

# fdisk -l /dev/sdi

ディスク /dev/sdi: 29.2 GiB, 31331450880 バイト, 61194240 セクタ
単位: セクタ (1 * 512 = 512 バイト)  ・・・
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: dos
ディスク識別子: 0xb765619f
デバイス   起動 開始位置 終了位置   セクタ サイズ Id タイプ
/dev/sdi1           8192  1056767  1048576   512M ea Rufus alignment   ・・・
/dev/sdi2        1056768 60555263 59498496  28.4G 83 Linux

# lsblk -f /dev/sdi

NAME   FSTYPE LABEL      UUID                                 MOUNTPOINT
sdi
 |-sdi1 vfat   armbi_boot A63B-8E78
 |-sdi2 ext4   armbi_root 1364b180-84ba-4ee5-b238-8aff727daf80

# mkdir /mnt/{sdi1,sdi2}
# mount /dev/sdi1 /mnt/sdi1
# mount /dev/sdi2 /mnt/sdi2
# df -h /mnt/sdi1 /mnt/sdi2

ファイルシス   サイズ  使用  残り 使用% マウント位置
/dev/sdi1        511M   70M  442M   14% /mnt/sdi1    ・・・
/dev/sdi2         28G  1.8G   26G    7% /mnt/ddi2       ・・・

# umount /mnt/sdi1
# umount /mnt/sdi2
# rmdir /mnt/sdi1 /mnt/sdi2

【バックアップ】

母艦OSの作業場所は、
・バックアップ /home/user01/backup

(1) MBR領域の取得

第1パーティションの開始セクターは8192。(【情報収集】 )
0~8191 までが、Loaderが起動されるまでの情報が保存されている。

  • fdiskの結果(【情報収集】 ) から、1セクタは512Byte よって、bs=512
  • セクターの0-8191まで取得したいので、count=8192

# dd if=/dev/sdi of=/home/user01/backup/dd-mbr-8192.img bs=512 count=8192

(2) 第1パーティションの取得

vfat領域の為、tarで取得

# mkdir /mnt/SDCARD
# mount /dev/sdi1 /mnt/SDCARD
# cd /mnt/SDCARD
# tar zcf /home/user01/backup/sdi1.tar.gz ./
# cd /
# umount /mnt/SDCARD
# rndir /mnt/SDCARD

(2) 第2パーティションの取得

ext4領域の為、dumpコマンドで取得。(この辺りは好みで)

# /sbin/dump -0u -z9 -b 20 -f /home/user01/backup/sdi2.dump /dev/sdi2 && sync

【イメージ作成】

母艦OSの作業場所は、
・作成場所 /home/user01/work

(1) ディスク容量の確保

今回2つのパーティションを作成するが、作成後に拡張出来るのは第2パーティション以降の空き容量を第2パーティションとする事が出来る。
よって第1パーティションは後で拡張出来な事を考慮する。(【情報収集】 , )

  • 第1パーティションは、そんまま512MB
  • 第2パーティションは、2GB
    計、2.5GBの領域を準備する。

# dd if=/dev/zero of=/home/user01/work/master.img bs=1M count=2500 && sync
 → fallocate コマンドでも良いが、最終的にxzで圧縮するので/dev/zero のほうが圧縮率が良さそう?

2500+0 レコード入力
2500+0 レコード出力
2621440000 bytes (2.6 GB, 2.4 GiB) copied, 1.4998 s, 1.7 GB/s

# losetup -f /home/user01/work/master.img
# losetup -l

NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE                DIO LOG-SEC
/dev/loop0         0      0         0  0 /home/user01/work/master.img   0     512

(2) MBR領域の展開

バックアップしたMBRのイメージ dd-mbr-8192.img を展開する。

# dd if=/home/user01/backup/dd-mbr-8192.img of=/dev/loop0

8192+0 レコード入力
8192+0 レコード出力
4194304 bytes (4.2 MB, 4.0 MiB) copied, 0.086115 s, 48.7 MB/s

(3) fdiskで領域の修正

# fdisk -l /dev/loop0

ディスク /dev/loop0: 2.5 GiB, 2621440000 バイト, 5120000 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: dos
ディスク識別子: 0xb765619f
デバイス     起動 開始位置 終了位置   セクタ サイズ Id タイプ
/dev/loop0p1          8192  1056767  1048576   512M ea Rufus alignment
/dev/loop0p2       1056768 60555263 59498496  28.4G 83 Linux

/dev/loop0 の総容量は2.5GBに対して、強制的に32GBのSDカードのMBR領域を上書きしたので、
第2パーティション /dev/loop0p2 の終了位置 60555263が、最大5120000 セクタを超えている。
第2パーティションを削除/新規作成して正しい状態に戻す。

# fdisk /dev/loop0
  p (確認)
  d -> 2 (第2パーティション削除)
  n -> p -> 2 -> 1056768(開始位置) -> 5119999(終了位置) ※値は既定値最大
  p (確認)
  w (書込み)

パーティション情報の再読み込みに失敗しました。: Invalid argument
カーネルは古い情報を使用しています。新しい情報を利用するには、システムを再起動するか、もしくは partprobe(8) または kpartx(8) を実行してください。

(4) 第1/第2パーティションのファイルシステム作成

使用している母艦OSでは、/dev/loop0p1, /dev/loop0p2 が作成出来ずに、partprobe or kpartx で認識させる事になる。

# kpartx -a /dev/loop0
# ls -l /dev/mapper/loop0p*

lrwxrwxrwx 1 root root 7 11月 24 07:43 /dev/mapper/loop0p1 -> ../dm-0
lrwxrwxrwx 1 root root 7 11月 24 07:43 /dev/mapper/loop0p2 -> ../dm-1

パーティションラベルとUUIDを指定して、ファイルシステムを作成
# mkfs.vfat -n armbi_boot -i A63B8E78 /dev/mapper/loop0p1
# mkfs.ext4 -L armbi_root -U 1364b180-84ba-4ee5-b238-8aff727daf80 /dev/mapper/loop0p2

パーティションラベルとUUIDが指定した通りとなっているか確認
# lsblk -i -f /dev/loop0

NAME      FSTYPE LABEL      UUID                                 MOUNTPOINT
loop0
|-loop0p1 vfat   armbi_boot A63B-8E78
`-loop0p2 ext4   armbi_root 1364b180-84ba-4ee5-b238-8aff727daf80

(5) 第1/第2パーティションのデータリストア

# mkdir /mnt/{sdi1,sdi2}
# mount /dev/sdi1 /mnt/sdi1
# mount /dev/sdi2 /mnt/sdi2

# cd /mnt/sdi1
# tar zxfv /home/user01/backup/sdi1.tar.gz
# cd /mnt/sdi2
# restore -r -f /home/user01/backup/sdi2.dump && sync
# rm restoresymtable

# cd /
# umount /mnt/sdi1
# umount /mnt/sdi2
# rmdir /mnt/sdi1 /mnt/sdi2

(6) loop0デバイスの解除

# kpartx -d /dev/loop0
# ls -l /dev/mapper/

合計 0
crw------- 1 root root 10, 236 11月 24 07:43 control

# losetup -l

NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE                      DIO LOG-SEC
/dev/loop0         0      0         0  0 /home/user01/work/master.img   0     512

# losetup -d /dev/loop0
# losetup -l
(loop0デバイスが未割当状態を確認)

# ls -lh /home/user01/work

-rw-r--r-- 1 root root 2.5G 11月 24 08:17 master.img

(7) 中間ファイル削除

# rm -fr /home/user01/backup

# xz /home/user01/work/master.img
# ls -lh /home/user01/work

-rw-r--r-- 1 root root 535M 11月 24 08:17 master.img.xz

以上で完成である。
SDカードのディスクイメージ 32GBが、圧縮させると535MBとなるので保管や配布等には向いている。