raspbianベースのオリジナルイメージファイルを作成する

# 概要

Raspberry Piで主に使用されるOSであるRaspbianはイメージファイルをPC等でmicroSDカードに書き込み、Raspberry Piに挿入することで起動する。
また、microSDカード上のデータをイメージとしてコピーすれば、オリジナルのイメージファイルを取得できる。これ別のmicroSDに書き込めば、同じデータ・設定のRaspbeery Piを複数作成できる。
一方で、イメージのコピーの際、以下の問題がある。

* microSDカードの容量に比例して、バックアップに時間がかかる
* microSDカード上で使用していない容量の分もイメージのサイズに含まれてしまう



本記事は以下の手順を記す。

* Raspbianのパーティション自動拡張機能をOFFにする方法  
* microSDをWindows上でバックアップ  



# 使用したソフト

すべて、WindowsPC上にインストール。
// Mac・Linuxであればいずれも必要ないであろう。

* Visual Studio Code  
utf-8形式のファイルを編集できればよい。
* Git for Windows  
ddコマンド実行に使用する。MINGW64が使えれば良いと思われる。
* balenaEtcher  
イメージをSDカードに記録するソフト。


# 手順

## Raspbianのパーティション自動拡張機能をOFFにする方法

Raspbianは初回起動時に、microSDカードの全領域を利用できるようパーティション拡張を行う仕様となっている。このまま起動すると、パーティションが拡張されmicroSDカード全体をコピーしなければならなくなるので、この機能をOFFにする。


まず、RaspbianのOSイメージをダウンロードし、EtcherでmicroSDカードに焼く。
ここでは、最新の2019-07-10-raspbian-buster-lite.imgを用いている。
※ddコマンドを使ってもよいが、Etcherの方が進行状況がわかりやすい。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189186/62d3aa42-ba8b-dcf2-d2f4-fe9b3516c215.png" width=60%>

microSDカードをWindows上でマウントし、設定ファイルを変更していく。

microSDを一度PCから取り外し、再度挿入すると、"boot"というドライブが認識される。
"boot"ドライブにある`cmdline.txt`を開き、`init=/usr/lib/raspi-config/init_resize.sh`という記述を削除する。

```bash:before
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=17869b7d-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet init=/usr/lib/raspi-config/init_resize.sh
```

```bash:after
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=17869b7d-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet
```

この状態のmicroSDカードをRaspberry Piに入れて起動すると、ファイルパーティションの拡張が行われず、最小限のパーティションのままとなる。

## windows上でのmicroSDのコピー

Raspberry Pi上で作業してイメージファイルを作成したい状態にしておく。
また、このタイミングで`sudo raspi-config  --expand-rootfs`を実行しておくと、オリジナルイメージの初回起動時にパーティション拡張が行われる。

Raspberry Pi上で`sudo fdisk -l`を実行する。

以下のように表示される。

```bash
Disk /dev/mmcblk0: 7.5 GiB, 8021606400 bytes, 15667200 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: 0x17869b7d

Device         Boot  Start     End Sectors  Size Id Type
/dev/mmcblk0p1        8192  532480  524289  256M  c W95 FAT32 (LBA)
/dev/mmcblk0p2      540672 4292607 3751936  1.8G 83 Linux
```

`/dev/mmcblk0p2`の行を見ると、Endの列に4292607とある。

この番号をメモしたら、`sudo shutdown -h now`としRaspberry Piをシャットダウンする。

以降、Windows PCで作業する。

スタートメニューでGit Bashを探し、右クリックして管理者権限で起動する。
次に、Raspberry Piから取り出したmicroSDカードをPCに挿入する。

ddコマンドでイメージファイルへのmicroSDのコピーを行う。
まず、コピー元となるmicroSDカードのブロックデバイスを確認する。

```bash
ls /dev/sd*
/dev/sda  /dev/sda1  /dev/sda2  /dev/sda3  /dev/sda4  /dev/sdb  /dev/sdb1  /dev/sdb2
```

筆者の環境では、/dev/sdbとしてmicroSDが見えている。


countオプションでコピーするサイズを指定することで、必要な部分のみコピーする。countに指定する値は、以下で求める。[^1]

末尾のセクタ番号×1セクタあたりのサイズ÷ベースサイズ

先程`fdisk`コマンドで確認した、microSDカード上でパーティションの末尾のセクタ番号は4292607であった。1セクタあたりのサイズは固定で512バイト。
今回はベースサイズを1Mバイト(1024*1024バイト)とする。

4292607×512÷(1024×1024)＝2095.99951171875・・・

よって、countには2096を指定する。

```bash
dd if=/dev/sdb of=original.img bs=1M count=2096
```

上記コマンドで、オリジナルのイメージファイルを取得できる。


# 参考文献

* https://dev.classmethod.jp/hardware/raspberrypi-backup-restore/

# 備考

[^1]: 参考文献では、末尾セクタ番号÷2048としているのだが、2048がいきなり出てくる理由が理解できなかった。