前回カーネルも差し替えたので、以前の記事を見ながらディスクイメージのバックアップを取ろうかと思ったのですが、以前に構築した Linux Mint の仮想環境で、VirtualBox が(なぜか)ホスト側に挿した microSD カードリーダをうまく認識してくれませんでした。
仕方がないので、ディスクイメージをコネコネして、パーティションのリサイズやら何やらを行なったディスクイメージを作成することにしました。
gparted でリサイズしようと思ったんですが、アレ?イメージファイルだと、何故かリサイズ出来ないですね。。。
ちなみに、前回カーネルを差し替えたものに加えて、
NTP設定、不要デーモンの停止、RAMディスクの使用、SWAPの停止、を行なっています。
SD使用量の節約のため日本語化等は見送りました。
ディスク使用量は半分弱といったところです。
◆ディスクイメージのベースの作成
"Win32 Disk Imager" を使用して、microSD のディスクイメージを Read し、仮想環境からも見える共有フォルダに入れておきます。以下、仮想環境の Linux Mint での操作になります。
(以下、ディスクイメージを rpi.img というファイル名で取得したとして記載しています。)
まずは、作成するディスクイメージのサイズを決めます。
今回は4GBのmicroSDをしようしているので、半分の2GBにしてみようと思います。
まず、空のファイルをイレモノとして作ります。
元のサイズの半分にした値
(7716863 + 1) / 2 = 3858432
をcountに指定します。
# ちなみに、fdisk の表示される値と単位を合わせる意味で bs=512 としていますが、
# bs を(8倍の) 4096 とかにした方が、ファイルの作成時間は短くなります。
# その場合、count は(8分の1の)482304 とする必要があります。
# 詳細は↓おまけ1参照
パーティションテーブルを作成し、パーティションを2つ作成します。
fdisk コマンドで対話モードで設定しても全然問題ないんですが、表現が難しいので下記のようなコマンドにしておきます。(凄く見にくいですが、$'\n' が改行と思ってください。)
これでガワだけは出来ました。
# 最初はこのディスクイメージを "sudo kpartx -v -a ${IMGFILE}" して、
# "mkfs.ext4 /dev/mapper/loop0p2" とかして直接フォーマットしようとしたんですが、
# 何かうまく出来なくてmountも出来ないので、下記のような手順を踏む事にしました。
◆各パーティションイメージの作成
それぞれ
(122879 + 1) - 8192 = 114688
(3858431 + 1) - 122880 = 3735552
の値を指定し、各パーティションのイメージファイルを作成します。
元のイメージディスクをマウントします。
◆ディスクイメージとして結合
ベースのディスクイメージの各パーティションを置き換えて出来上がりです。
ちなみに、このディスクイメージは圧縮したら 400MB 弱になりました。
◆おまけ1
dd コマンドでは "bs=512, count=2048" でも、"bs=1024, count =1024" でも、どちらでも 1MB (bs * count) の読み書きを行なう、という事には変わりありません。では動きとしてはどう違うのでしょうか?
dd コマンドでは、if で指定したファイルから bs 単位で read し、of で指定したファイルに bs 単位で write を行う、という操作を count 回数分繰り返します。
つまり bs 単位の read, write システムコールを count 回発行しているのです。
以下のように、strace で観察するとよく分かります。
仕方がないので、ディスクイメージをコネコネして、パーティションのリサイズやら何やらを行なったディスクイメージを作成することにしました。
gparted でリサイズしようと思ったんですが、アレ?イメージファイルだと、何故かリサイズ出来ないですね。。。
ちなみに、前回カーネルを差し替えたものに加えて、
NTP設定、不要デーモンの停止、RAMディスクの使用、SWAPの停止、を行なっています。
SD使用量の節約のため日本語化等は見送りました。
ディスク使用量は半分弱といったところです。
$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/root 3671884 1623100 1849424 47% /
devtmpfs 219996 0 219996 0% /dev
tmpfs 44836 336 44500 1% /run
tmpfs 5120 0 5120 0% /run/lock
tmpfs 89660 0 89660 0% /run/shm
/dev/mmcblk0p1 57288 10200 47088 18% /boot
tmpfs 32768 0 32768 0% /tmp
tmpfs 32768 112 32656 1% /var/log
◆ディスクイメージのベースの作成
"Win32 Disk Imager" を使用して、microSD のディスクイメージを Read し、仮想環境からも見える共有フォルダに入れておきます。以下、仮想環境の Linux Mint での操作になります。
(以下、ディスクイメージを rpi.img というファイル名で取得したとして記載しています。)
$ fdisk -l /media/sf_shared/rpi.img
ディスク /media/sf_shared/rpi.img: 3951 MB, 3951034368 バイト
ヘッド 255, セクタ 63, シリンダ 480, 合計 7716864 セクタ
Units = セクタ数 of 1 * 512 = 512 バイト
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスク識別子: 0x0009bf4f
デバイス ブート 始点 終点 ブロック Id システム
/media/sf_shared/rpi.img1 8192 122879 57344 c W95 FAT32 (LBA)
/media/sf_shared/rpi.img2 122880 7716863 3796992 83 Linux
まずは、作成するディスクイメージのサイズを決めます。
今回は4GBのmicroSDをしようしているので、半分の2GBにしてみようと思います。
まず、空のファイルをイレモノとして作ります。
元のサイズの半分にした値
(7716863 + 1) / 2 = 3858432
をcountに指定します。
$ export IMGFILE=/media/sf_shared/new.imgこれで、単にゼロ埋めされた2GBのファイルが出来上がりました。
$ dd if=/dev/zero of=${IMGFILE} count=3858432 bs=512
# ちなみに、fdisk の表示される値と単位を合わせる意味で bs=512 としていますが、
# bs を(8倍の) 4096 とかにした方が、ファイルの作成時間は短くなります。
# その場合、count は(8分の1の)482304 とする必要があります。
# 詳細は↓おまけ1参照
パーティションテーブルを作成し、パーティションを2つ作成します。
fdisk コマンドで対話モードで設定しても全然問題ないんですが、表現が難しいので下記のようなコマンドにしておきます。(凄く見にくいですが、$'\n' が改行と思ってください。)
$ echo o$'\n'w | fdisk ${IMGFILE}
$ echo n$'\n'p$'\n'$'\n'8192$'\n'122879$'\n'w | fdisk ${IMGFILE}
$ echo n$'\n'p$'\n'$'\n'122880$'\n'3858431$'\n'w | fdisk ${IMGFILE}
$ echo t$'\n'1$'\n'c$'\n'w | fdisk ${IMGFILE}
これでガワだけは出来ました。
$ fdisk -l ${IMGFILE}
ディスク /media/sf_shared/new.img: 1975 MB, 1975517184 バイト
ヘッド 255, セクタ 63, シリンダ 240, 合計 3858432 セクタ
Units = セクタ数 of 1 * 512 = 512 バイト
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスク識別子: 0x0177f305
デバイス ブート 始点 終点 ブロック Id システム
/media/sf_shared/new.img1 8192 122879 57344 c W95 FAT32 (LBA)
/media/sf_shared/new.img2 122880 3858431 1867776 83 Linux
# 最初はこのディスクイメージを "sudo kpartx -v -a ${IMGFILE}" して、
# "mkfs.ext4 /dev/mapper/loop0p2" とかして直接フォーマットしようとしたんですが、
# 何かうまく出来なくてmountも出来ないので、下記のような手順を踏む事にしました。
◆各パーティションイメージの作成
それぞれ
(122879 + 1) - 8192 = 114688
(3858431 + 1) - 122880 = 3735552
の値を指定し、各パーティションのイメージファイルを作成します。
$ dd if=/dev/zero of=boot.img count=114688 bs=512それぞれフォーマットします。
$ dd if=/dev/zero of=rootfs.img count=3735552 bs=512
$ mkfs.vfat boot.img
$ mkfs.ext4 -F rootfs.img
元のイメージディスクをマウントします。
$ mkdir old1/ old2/ new1/ new2/元のイメージディスクの中身をそれぞれ全コピーします。
$ sudo kpartx -v -a /media/sf_shared/rpi.img
$ sudo mount /dev/mapper/loop0p1 old1/
$ sudo mount /dev/mapper/loop0p2 old2/
$ sudo mount boot.img new1/その他変更等(.bash_history や /var/cache/* の削除等)、やりたければやって、気が済めばアンマウントします。
$ sudo mount rootfs.img new2/
$ sudo cp -a old1/* new1/
$ sudo cp -a old2/* new2/
$ sudo umount new1/元のイメージディスクをアンマウントします。
$ sudo umount new2/
$ sudo umount old1/
$ sudo umount old2/
$ sudo kpartx -d /media/sf_shared/rpi.img
$ rmdir old1/ old2/ new1/ new2/
◆ディスクイメージとして結合
ベースのディスクイメージの各パーティションを置き換えて出来上がりです。
$ dd if=boot.img of=${IMGFILE} seek=8192 bs=512これを "Win32 Disk Imager" で microSD に書き込めば、いつでもこの環境に復帰できます。
$ cat rootfs.img >> ${IMGFILE}
ちなみに、このディスクイメージは圧縮したら 400MB 弱になりました。
◆おまけ1
dd コマンドでは "bs=512, count=2048" でも、"bs=1024, count =1024" でも、どちらでも 1MB (bs * count) の読み書きを行なう、という事には変わりありません。では動きとしてはどう違うのでしょうか?
dd コマンドでは、if で指定したファイルから bs 単位で read し、of で指定したファイルに bs 単位で write を行う、という操作を count 回数分繰り返します。
つまり bs 単位の read, write システムコールを count 回発行しているのです。
以下のように、strace で観察するとよく分かります。
$ strace dd if=/dev/zero of=dummy count=100 bs=512
execve("/bin/dd", ["dd", "if=/dev/zero", "of=dummy", "count=100", "bs=512"], [/* 48 vars */]) = 0
brk(0) = 0x9cf4000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
:
open("/dev/zero", O_RDONLY|O_LARGEFILE) = 3
dup2(3, 0) = 0
close(3) = 0
_llseek(0, 0, [0], SEEK_CUR) = 0
open("dummy", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
dup2(3, 1) = 1
close(3) = 0
clock_gettime(CLOCK_MONOTONIC, {238, 286988438}) = 0
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512
: