mattintosh note

田舎エンジニア物語 〜In Search of the Lost My Private Key〜

Linux USB 量産用のイメージを作成する

新入社員入社シーズン。企業によっては技術研修等を行っている時期でしょうか。私はつい先日まで出張講師で LPIC/LinuC を教えていたのですが、Linux はやはり実機で覚えるのが一番だと思います。しかし、会社の資産である Windows PC で Windows を削除して Linux をインストールするというのはなかなか受け入れてもらえません。

そのため、USB メモリから Linux を起動する方法を用いるのですが、実機を使って USB メモリひとつひとつに Linux をインストールするのはとても大変です。そこで、パワーのあるマシンで仮想マシンを作成してマスターイメージを作成し、Linux がインストールされた USB メモリを量産する方法を使います。

用意するもの

Windows マシンでも作成は可能ですが、vboxmanage コマンドへのパスが面倒なことと、dd コマンドが必要になるためここでは紹介しません。

ここで紹介する方法は最悪の場合、データの破損を招きますので作業は自己責任で行ってください。

ベースイメージを作成する

truncate コマンドでイメージファイルを作成します。USB メモリの表記容量は 10 の累乗になっているのでサイズは G ではなく GB で指定します。

linus@localhost:~$ truncate -s 8GB CentOS7.img

単位指定の方法の違いによるイメージファイルのサイズは下記のようになります。8G16G で指定すると USB メモリに収まらないことがあるので注意です。

linus@localhost:~$ truncate -s 8GB 8GB.img
linus@localhost:~$ truncate -s 8G 8G.img
linus@localhost:~$ ls -l 8GB.img 8G.img
-rw-rw-r-- 1 linus linus 8000000000  4月 30 15:47 8GB.img
-rw-rw-r-- 1 linus linus 8589934592  4月 30 15:47 8G.img

続いて作成したイメージファイルを VirtualBox で使えるように VMDK イメージを作成します。macOS の場合は /Applications/VirtualBox.app/Contents/MacOS の中に vboxmanage コマンドがあると思います。問題がなければ created successfully のメッセージが表示されます。

linus@localhost:~$ vboxmanage internalcommands creatrawvmdk -rawdisk CentOS7.img -filename CentOS7.vmdk
RAW host disk access VMDK file CentOS7.vmdk created successfully.

あとは通常通り仮想マシンを起動してインストールを進めていきます。

VirtualBox仮想マシンを作成し、ディスクの選択で「既存のディスクを選択」して、上記で作成した VMDK ファイルを指定します。使用する PC が BIOS ではなく UEFI の場合は仮想マシンの設定で EFI を有効にしておく必要があります。

f:id:mattintosh4:20190430200724p:plain
VirtualBox

インストールだけではなく、初期設定もしておきたい場合はここで済ませておきましょう。

イメージのバックアップ

インストールが完了したらイメージファイルをバックアップを作成しておくといいでしょう。圧縮方法には GZIP、BZIP2、XZ などがありますが、圧縮効率を優先するのであれば XZ が良いでしょう。

Debian 系の場合

Debian 系の場合は -k|--keep オプションが使えますので簡単に圧縮元のファイルを残しておくことができます。

linus@localhost:~$ xz -k CentOS7.img

RHEL 系の場合

RHEL 系は -k|--keep が使えないのでリダイレクトで作成します。

linus@localhost:~$ xz <CentOS7.img >CentOS7.img.xz

USB メモリへの書き込み

dd コマンドやディスクイメージライターで USB メモリにイメージを書き込みます。ここでは USB メモリが /dev/sdb に接続されているものとします。ブロックサイズ等はご自由に指定してください。macOS の場合は diskutils list コマンドで USB メモリのデバイスパスを確認してください。

書き込み先の指定を誤るとデータを破壊する可能性がありますので十分に注意してください。

linus@localhost:~$ sudo dd if=CentOS7.img of=/dev/sdb bs=16M conv=noerror,sync status=progress

圧縮された状態から書き込む場合はコマンドの標準出力から dd の標準入力に渡します。

linus@localhost:~$ xz <CentOS7.img.xz | sudo dd of=/dev/sdb

USB メモリを取り外します。

linus@localhost:~$ sync
linus@localhost:~$ sudo eject /dev/sdb

あとは同じ方法で USB メモリに書き込めば Linux がインストールされた USB メモリを量産することが出来ます。(パフォーマンス次第では複数同時に作成することも出来ます)

領域の拡張

今回の方法では USB メモリよりイメージサイズの方が小さくなるため USB メモリには未使用の領域が出来るはずです。ここからの手順で USB メモリの全領域を使えるようにしていきます。手順としては下記のようになります。

  1. パーティションテーブルを編集してパーティションを拡張する
  2. ファイルシステムを拡張する

LVM を使用している場合は少し手順が増えます。

  1. パーティションテーブルを編集してパーティションを拡張する
  2. LVM 物理ボリュームを拡張する
  3. LVM 論理ボリュームを拡張する
  4. ファイルシステムを拡張する

この作業は USB メモリにイメージを書き込んだあとにそのマシンで行ってもいいのですが、私の場合はパーティションテーブルについて理解してもらうため、受講者に各自のマシンで行ってもらっています。(USB メモリから起動すると /dev/sdaWindows の入ったディスクになるため十分に注意してもらう必要はあります)

USB メモリにインストールした OS で LVM を使用していない場合

MBR の場合は fdisk コマンド、GPT の場合は gdisk コマンドを使ってパーティションテーブルを操作します。ここでは USB メモリのデバイスパスが /dev/sdb だとします。ルートファイルシステムが含まれたパーティションを削除して新しいパーティションを作ります。

ubuntu@localhost:~$ sudo gdisk /dev/sdb

ディスクに変更を書き込んだら新しいパーティションテーブルを認識させるためシステムを再起動します。

次に、ファイルシステムを拡張しますが EXT 系と XFS ではファイルシステムの拡張に使用するコマンドが異なります。

EXT2/EXT3/EXT4 の場合は resize2fs で拡張します。ここではルートファイルシステムが含まれるパーティション/dev/sdb3 とします。

ubuntu@localhost:~$ sudo resize2fs /dev/sdb3

XFS の場合は xfs_grawfs で拡張します。ここではルートファイルシステムが含まれるパーティション/dev/sdb3 とします。

centos@localhost:~$ sudo xfs_grawfs /dev/sdb3

USB メモリにインストールした OS で LVM を使用している場合

CentOS7 の場合はデフォルトで LVM を使うようになっているかと思います。先に説明した通り、LVM を使用している場合はパーティションテーブルの編集に加え、物理ボリュームと論理ボリュームの拡張が必要になります。

まず、編集前の状態を確認します。ディスクは 16 GB として認識されていますが、パーティションファイルシステムは 8 GB のときのままになっています。

[root@localhost ~]# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0 14.9G  0 disk 
├─sda1            8:1    0  200M  0 part /boot/efi
├─sda2            8:2    0    1G  0 part /boot
└─sda3            8:3    0  6.3G  0 part 
  ├─centos-root 253:0    0  5.5G  0 lvm  /
  └─centos-swap 253:1    0  764M  0 lvm  [SWAP]
sr0              11:0    1 1024M  0 rom  
[root@localhost ~]# df -h
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root  5.5G  3.7G  1.9G  67% /
devtmpfs                 479M     0  479M   0% /dev
tmpfs                    496M     0  496M   0% /dev/shm
tmpfs                    496M  7.1M  489M   2% /run
tmpfs                    496M     0  496M   0% /sys/fs/cgroup
/dev/sda2               1014M  150M  865M  15% /boot
/dev/sda1                200M   12M  189M   6% /boot/efi
tmpfs                    100M     0  100M   0% /run/user/0

MBR であれば fdisk、GPT であれば gdisk を使ってルートパーティションを拡張します。

[root@localhost ~]# gdisk /dev/sda
GPT fdisk (gdisk) version 0.8.10

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): p ❶
Disk /dev/sda: 31250000 sectors, 14.9 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): D3D40B34-6318-4815-9C14-7E5605FD5815
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 31249966
Partitions will be aligned on 2048-sector boundaries
Total free space is 15627014 sectors (7.5 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048          411647   200.0 MiB   EF00  EFI System Partition
   2          411648         2508799   1024.0 MiB  0700  
   3         2508800        15624966   6.3 GiB     8E00  Linux LVM

Command (? for help): d ❷
Partition number (1-3): 3 ❸

Command (? for help): p ❹
Disk /dev/sda: 31250000 sectors, 14.9 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): D3D40B34-6318-4815-9C14-7E5605FD5815
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 31249966
Partitions will be aligned on 2048-sector boundaries
Total free space is 28743181 sectors (13.7 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048          411647   200.0 MiB   EF00  EFI System Partition
   2          411648         2508799   1024.0 MiB  0700  

次に、ルートファイルシステムが含まれるパーティションを再作成します。

Command (? for help): n ❶
Partition number (3-128, default 3): ❷
First sector (34-31249966, default = 2508800) or {+-}size{KMGTP}: ❸
Last sector (2508800-31249966, default = 31249966) or {+-}size{KMGTP}: ❹
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 8e00 ❺
Changed type of partition to 'Linux LVM'

Command (? for help): p ❻
Disk /dev/sda: 31250000 sectors, 14.9 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): D3D40B34-6318-4815-9C14-7E5605FD5815
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 31249966
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048          411647   200.0 MiB   EF00  EFI System Partition
   2          411648         2508799   1024.0 MiB  0700  
   3         2508800        31249966   13.7 GiB    8E00  Linux LVM

Command (? for help): w ❼

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y ❽
OK; writing new GUID partition table (GPT) to /dev/sda.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot.
The operation has completed successfully.
  • ❶ … 新しいパーティションを作成します。
  • ❷ … パーティション番号を指定します。空白のままでかまいません。
  • ❸ … 開始セクターを指定します。空白のままでかまいません。
  • ❹ … 終了セクターを指定します。空白のままでかまいません。
  • ❺ … パーティションタイプを指定します。Linux LVM は 8e00 です。
  • ❻ … パーティションテーブルを確認します。新しく作成されたパーティションが拡張されていることを確認します。
  • ❼ … 変更をディスクに書き込みます。
  • ❽ … y を指定して書き込みを実行します。

新しいパーティションテーブルをシステムに反映させるためにシステムを再起動します。

[root@localhost ~]# reboot

再起動したらルートファイルシステムが含まれるパーティションのサイズ(ここでは /dev/sda3)が拡張されていることを確認します。

[root@localhost ~]# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0 14.9G  0 disk 
├─sda1            8:1    0  200M  0 part /boot/efi
├─sda2            8:2    0    1G  0 part /boot
└─sda3            8:3    0 13.7G  0 part 
  ├─centos-root 253:0    0  5.5G  0 lvm  /
  └─centos-swap 253:1    0  764M  0 lvm  [SWAP]
sr0              11:0    1 1024M  0 rom  

この時点ではまだファイルシステムは拡張されていません。

[root@localhost ~]# df -h
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root  5.5G  3.7G  1.9G  67% /
devtmpfs                 479M     0  479M   0% /dev
tmpfs                    496M     0  496M   0% /dev/shm
tmpfs                    496M  7.1M  489M   2% /run
tmpfs                    496M     0  496M   0% /sys/fs/cgroup
/dev/sda2               1014M  150M  865M  15% /boot
/dev/sda1                200M   12M  189M   6% /boot/efi
tmpfs                    100M     0  100M   0% /run/user/0

続いて、LVM の物理ボリュームを拡張します。pvs コマンドや pvdisplay コマンドで物理ボリュームのサイズを確認しておきます。

[root@localhost ~]# pvs
  PV         VG     Fmt  Attr PSize PFree
  /dev/sda3  centos lvm2 a--  6.25g    0 

pvresize コマンドを使って物理ボリュームを拡張します。

[root@localhost ~]# pvresize /dev/sda3
  Physical volume "/dev/sda3" changed
  1 physical volume(s) resized or updated / 0 physical volume(s) not resized

再度 pvs コマンドや pvdisplay コマンドで物理ボリュームが拡張されていることを確認します。

[root@localhost ~]# pvs
  PV         VG     Fmt  Attr PSize  PFree
  /dev/sda3  centos lvm2 a--  13.70g 7.45g

物理ボリュームが拡張できたら論理ボリュームの拡張を行います。lvs コマンドや lvdisplay コマンドで論理ボリュームのサイズを確認しておきます。

[root@localhost ~]# lvs
  LV   VG     Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root centos -wi-ao----   5.50g                                                    
  swap centos -wi-ao---- 764.00m                                                    

lvextend コマンドで空き領域すべてを使って拡張します。--resizefs オプションを加えておくとファイルシステムの拡張まで一緒に行ってくれます。

[root@localhost ~]# lvextend -l +100%free --resizefs /dev/centos/root
  Size of logical volume centos/root changed from 5.50 GiB (1409 extents) to <12.96 GiB (3317 extents).
  Logical volume centos/root successfully resized.
meta-data=/dev/mapper/centos-root isize=512    agcount=4, agsize=360704 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=1442816, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 1442816 to 3396608

lvs コマンドまたは lvdisplay コマンドで論理ボリュームが拡張されていることを確認します。

[root@localhost ~]# lvs
  LV   VG     Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root centos -wi-ao---- <12.96g                                                    
  swap centos -wi-ao---- 764.00m                                                    

最後にファイルシステムが拡張されていることが確認できれば作業完了です。

[root@localhost ~]# df -h
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   13G  3.7G  9.3G  29% /
devtmpfs                 479M     0  479M   0% /dev
tmpfs                    496M     0  496M   0% /dev/shm
tmpfs                    496M  7.1M  489M   2% /run
tmpfs                    496M     0  496M   0% /sys/fs/cgroup
/dev/sda2               1014M  150M  865M  15% /boot
/dev/sda1                200M   12M  189M   6% /boot/efi
tmpfs                    100M     0  100M   0% /run/user/0