続・玩式草子 ―戯れせんとや生まれけん―

第55回Plamo Linuxの遊び方(その6)

前回はon memory(RAM)上で動くPlamo Linuxの小規模環境(以下⁠mini-Plamo⁠⁠)を作成し、ISOイメージ化するまでを紹介しました。今回は、このmini-Plamo環境にパッケージを追加、削除してカスタマイズしたり、ISOイメージだけではなくUSBメモリからもブートできるようにしてみます。

mini-Plamoの機能確認

カスタマイズを行うまえに、このmini-Plamoのままで何ができるか確認しておきましょう。前回の手順のようにPlamo Linuxの⁠01_minimum⁠カテゴリをインストールすると、およそ180のパッケージがインストールされます。

インストールされるパッケージ群は動作に必須のカーネルやglibc、シェル等だけでなく、coreutilsutil_linuxgrepsedgawkといった基本ツール類、ethtoolsiputilsiproute2といったネットワーク用ツール、hdparmlshwprocps_ngpsmisc等のハードウェア/システム監視用ツール、e2fsprogsbtrfs_progsxfsproglsといったファイルシステム用ツール、vimemacsといったエディタ等、Linuxシステムの運用管理に必要なツールがほぼ揃っています。

またdhclientsshdも自動起動するものの、デフォルトではrootユーザのssh接続は禁止しているので、このままでは外部から利用することができません。そこでテストを兼ねて一般ユーザ用のアカウントを作り、外部からのログインを試してみましょう。

まずはコンソールからrootでログインし新規ユーザを作ります。今回はユーザ名⁠plamo⁠⁠、パスワードも⁠plamo⁠としましょう。Linuxの新規ユーザ作成コマンドは⁠useradd⁠ですが、このコマンドは引数指定が面倒なので、Plamo Linuxではadduserという対話型のラッパーコマンドを用意して、CUIなものの対話的に新規ユーザを作成できるようにしています。

一般ユーザ(⁠⁠plamo⁠⁠)を作成すれば、外部からIPアドレスを指定してリモートログインできます。手元の仮想環境ではDHCPで192.168.1.131というアドレスが割り当てられたので、⁠plamo@192.168.1.131⁠の指定でssh接続できました。

一般ユーザを作ってリモートログイン
一般ユーザを作ってリモートログイン

mini-Plamoのカスタマイズ

前節で紹介したように、mini-Plamo環境はユーザの新規登録やパッケージの追加等も可能なものの、メモリー上に展開されたinitramfsで動いているため、電源を落せば元の状態に戻ってしまいます。永続的に使いたい機能はinitramfsに組み込む必要があり、そのためには前回VirtualBoxから吸い出したVboxHDDディレクトリに戻っての作業となります。

$ ls VBoxHDD/
bin/    dev/  home/  lib/    lost+found/  mnt/   root/  sbin/  tmp/  var/
cdrom/  etc/  init@  lib64/  media/       proc/  run/   sys/   usr/

手順としては、このVBoxHDD/以下にchrootして必要な設定やパッケージを追加し、その環境を再度initramfsにまとめ直す、ということになります。

まず、chroot先の環境から各種システム情報を利用できるようにするため、/proc、/sys、/devをVBoxHDD/以下にバインド・マウントします。ついでにパッケージのインストール用にISOイメージをloopbackでマウントしておきましょう。

$ sudo mount --bind /dev ./VBoxHDD/dev
$ sudo mount --bind /proc ./VBoxHDD/proc
$ sudo mount --bind /sys ./VBoxHDD/sys
$ sudo mount -o loop,ro /Srcs/Plamo-8/plamo-8.2_x86_64_2024-03-29_usb.iso ./VBoxHDD/cdrom

あとはこのVBoxHDD/にchrootして、必要な設定やパッケージを追加するだけです。例として、先に試した⁠plamo⁠ユーザの事前登録とPythonパッケージをインストールしてみます。

$ sudo chroot ./VBoxHDD/
# ls
bin/    dev/  home/  lib/    lost+found/  mnt/   root/  sbin/  tmp/  var/
cdrom/  etc/  init@  lib64/  media/       proc/  run/   sys/   usr/
# adduser
Can you read Japanese chars on this term? [Y/n]
y
Japanese mode

新しいユーザのログイン名を指定してください(8 文字以内)。 []: plamo
plamo のユーザ ID は? [自動登録の場合は 1000 番台になります]: 
...
#

ついでにplamoユーザからsudoできるように、visudoで/etc/sudoersを修正しておきます。

# visudo
...
## User privilege specification
##
root ALL=(ALL:ALL) ALL
plamo ALL=(ALL:ALL) ALL
...

もう1ヵ所、/etc/fstabからルートパーティション(⁠⁠/⁠⁠)の設定を削除しておきます。これは本来、前回指摘しておかねばならない項目だったものの、執筆過程であれこれ試行錯誤しているうちに失念していました (_ _)。

# vim /etc/fstab
/dev/sda1       /        ext2        defaults   1   1    ←この行を削除する。
/dev/sr0         /cdrom         iso9660    user,ro,noauto,exec,iocharset=utf8 0   0
proc             /proc          proc       defaults   0   0
tmpfs            /run           tmpfs      defaults   0   0
...

initramfs上の/etc/fstabにルートパーティションの設定が残っていると、起動時のfsckに引っかかって起動しないことがあります。

前回の手順ではinitramfsを作成したのと同じ環境でテストしていたので、ルートパーティションの設定が残っていても露見しないため見逃してました。

さて、次に追加パッケージのインストールに移ります。loopbackマウントしたISOイメージは/cdrom以下に見えるので、/cdrom/plamo/02_dev/にあるPython-3.11.8パッケージをインストールします。

# ls /cdrom/
ChangeLog  README    efiboot.img  plamo/     plamo-8.1
EFI/       contrib/  isolinux/    plamo-8.0  plamo-8.2
# installpkg /cdrom/plamo/02_devel/Python-3.11.8-x86_64-B1.tzst
Python-3.11.8-x86_64-B1([required]) のインストール中
PACKAGE DESCRIPTION:
Python: Python3
Python:   
Python: 仕様を洗練するために後方互換性を捨てて進化したPythonの新バー
Python: ジョン。Python2と共存するためにコマンド名は python3
Python: になっています。
Python:   
Python-3.11.8-x86_64-B1 のインストールスクリプトを実行中
# python -V
Python 3.11.8

インストールが終わればchroot環境を終了し、./VBoxHDD/内へマウントしたディレクトリを解放します。アンマウントを忘れるとinitramfsにこれらのディレクトリの中身が入り込んでしまうのでご注意ください。

# exit
$ for i in proc sys dev cdrom ; do
  > sudo umount ./VBoxHDD/$i
  > done
$

あとは前回同様の方法でパッケージを追加したVBoxHDD/以下をinitramfsに固め、ISOimg/isolinux/以下のinitramfs.tzstに置き替えてISOイメージを作り直します。

$ su
password:
# cd VBoxHDD
# find . | cpio -ov -Hnewc | zstd -12 > ../new_initramfs.tzst
....

# cd .. ; ls -lh
drwxr-xr-x 20 kojima users  313  4月  2日  12:40 VBoxHDD/
-rw-r--r--  1 root   root  820M  4月  3日  08:47 new_initramfs.tzst

# ls -lh ISOimg/isolinux/
合計 764M
-rw-r--r-- 1 root   root  746M  2月 27日  00:32 initramfs.tzst
-rw-r--r-- 1 kojima users  44K  2月 27日  11:12 isolinux.bin
-rw-r--r-- 1 kojima users  146  2月 27日  11:23 isolinux.cfg
-rwxr-xr-x 1 kojima users 120K  2月 27日  11:12 ldlinux.c32*
-rwxr-xr-x 2 kojima users 9.2M  2月 27日  11:13 vmlinuz*
-rwxr-xr-x 2 kojima users 9.2M  2月 27日  11:13 vmlinuz-6.6.15-plamo64*
# rm -f ISOimg/isolinux/initramfs.tzst
# mv new_initramfs.tzst ISOimg/isolinux/initramfs.tzst
# exit
$ xorrisofs -o testimg_02.iso  -b isolinux/isolinux.bin -no-emul-boot \
  -boot-load-size 4 -boot-info-table ISOimg
...
$ ls -lh *iso
-rw-r--r-- 1 kojima users 755M  2月 27日  12:28 testimg.iso
-rw-r--r-- 1 kojima users 829M  4月  3日  09:38 testimg_02.iso

追加したPython-3.11.8パッケージのサイズが74MBなので、ISOイメージのサイズもその分増加しています。作り直したISOイメージを起動したところ、外部から⁠plamo⁠ユーザでログインでき、Pythonで実装しているget_pkginfoコマンドも問題なく動作しました。

Pythonを追加したISOイメージで起動
Pythonを追加したISOイメージで起動

USBメモリからの起動

Plamo Linuxではこうして作ったmini-Plamoをインストーラの基盤に使っているものの、mini-Plamo自体は汎用的な小規模Linuxシステムなので、起動しなくなったPCを復旧する際のレスキューツールとしても使えます。

Plamo LinuxのインストーラはDVD用のISOイメージとして作成していて、USBメモリからインストールする際もISOイメージをベタ書きした疑似DVDとして扱っていますが、レスキューツールとして使う場合は書き込みもできるUSBメモリとして使えた方が便利です。そこで今回は通常のUSBメモリからmini-Plamoを起動する方法を紹介しましょう。もっとも、この話題は以前にも取り上げたことがあるので、詳しい話はそちらを参照してもらうことにして、以下では概要の紹介程度にします。

USBメモリ起動用のgrubイメージの作成

GRUB(GRand Unified Bootloader)はさまざまな環境に柔軟に対応できる汎用ブートローダとして設計され、機能を細かく分割したモジュール群から構成されています。それらモジュールを組み合わせて実際の実行イメージを作成するのがgrub-mkimageコマンドです。

$ grub-mkimage -v -p '' -o bootx64.efi -O x86_64-efi fat part_msdos iso9660 gzio \
    all_video gfxterm font terminal normal linux echo test search configfile cpuid minicmd
grub-mkimage: 情報: the total module size is 0x92170.
grub-mkimage: 情報: reading /usr/lib/grub/x86_64-efi/kernel.img.
grub-mkimage: 情報: locating the section .text at 0x0.
...
grub-mkimage: 情報: kernel_img=0x7fdfdfe60010, kernel_size=0x1e000.
grub-mkimage: 情報: the core size is 0xb0170.
grub-mkimage: 情報: writing 0xb4000 bytes.
$ ls -lh bootx64.efi 
-rw-r--r-- 1 kojima users 720K  4月  3日  13:36 bootx64.efi
$ file bootx64.efi 
bootx64.efi: PE32+ executable (EFI application) x86-64 (stripped to external PDB), for MS Windows, 4 sections

USBメモリ上に起動用領域を設置

作成したUEFI用grubブートローダ(bootx64.efi)をUSBメモリ上に配置します。PCのマザーボードに組み込まれたUEFIは、接続された周辺機器を調べ、HDDの場合はESP(EFI System Partition)上にブートローダがあるか、HDD以外の機器ならばそのルートディレクトリの\EFI\BOOT\ディレクトリにブートローダがあるかを確認します。そのため、USBメモリをUEFI環境で起動メディアにしたい場合、そのルートディレクトリに\EFI\BOOT\ディレクトリを作り、そこにブートローダを置く必要があります。なお、USBメモリは接続すると自動的に/run/media/...以下にマウントされますが、環境によって異なるパスを示しても意味ないので、以下では/USBにマウントされているものとして示します。すなわち/USB/EFI/はUSBメモリのルートパーティションに作成されたEFIディレクトリです。

$ mkdir -p /USB/EFI/BOOT
$ cp bootx64.efi /USB/EFI/BOOT

カーネルとinitramfsはISOイメージ同様、isolinuxディレクトリに収めることにします。

$ mkdir -p /USB/isolinux
$ cp ISOimg/isolinux/{vmlinuz-6.6.15-plamo64,initramfs.tzst} /USB/isolinux

grubブートローダ用の設定ファイル(grub.cfg)をbootx64.efiと同じ場所に用意します。

$ cat << EOF > /USB/EFI/BOOT/grub.cfg
menuentry "mini-Plamo on USB" {
    linux (hd0,msdos1)/isolinux/vmlinuz-6.6.15-plamo64 root=/dev/ram0 ro net.ifnames=0 edd=off
    initrd (hd0,msdos1)/isolinux/initrd.tzst
}
EOF
$

UEFIな起動用USBメモリは以上の設定で完成です。後はPC起動時のUEFIメニューから起動デバイスとしてUSBメモリ上のUEFI環境を指定するだけです。

UEFI用ISOイメージの作成

さて、ついでなのでUEFI環境で起動できるISOイメージも作ってみましょう。ISOイメージをUEFI経由で起動する場合、前回紹介したsyslinuxのisolinux.binではなく、先に作ったbootx64.efiを収めたFDイメージから起動する流れになります。このあたりも詳細は過去の回を参照してください。

まず、ブートローダ(bootx64.efi)を収めるためのFDイメージファイルを作成します。

$ dd if=/dev/zero of=efiboot.img bs=1k count=1440
1440+0 records in
1440+0 records out
1474560 bytes (1.5 MB, 1.4 MiB) copied, 0.0337408 s, 43.7 MB/s
$ /usr/sbin/mkfs.msdos -F 12 -M 0xf8 efiboot.img
mkfs.fat 4.2 (2021-01-31)

作成したFDイメージファイル(efiboot.img)をloopbackマウントしブートローダを持ち込みます。この場合もUEFIが探すのは\EFI\BOOT\以下なので、あらかじめディレクトリ構造を作っておきます。

$ mkdir /tmp/loop
$ sudo mount -o loop efiboot.img /tmp/loop
$ sudo mkdir -p /tmp/loop/EFI/BOOT
$ sudo cp bootx64.efi /tmp/loop/EFI/BOOT

作成したefiboot.imgをISOイメージの作成領域に移します。

$ sync ; sudo umount /tmp/loop
$ mv efiboot.img ./ISOimg

UEFI環境でDVDメディア(ISO9660ファイルシステム)から起動するにはISO9660ファイルシステム上に後述するEl Torito代替起動メディアを用意する必要があります。El Torito代替起動メディアが設定された場合、UEFIはそのメディア上の\EFI\BOOT\にブートローダがあるかを調べます。上記⁠efiboot.img⁠に\EFI\BOOT\bootx64.efiを設置するのはそのためです。

一方、UEFIから起動されたbootx64.efiは自らの設定ファイル(grub.cfg)を探しに行くものの、その時点では(UEFIの管轄である)El Torito代替起動メディアは見えなくなっているので、探す先はDVDメディア上となります。そのため、grub.cfgはISOイメージの作業領域内に作った\EFI\BOOT\に置く必要があることになります。

$ mkdir -p ./ISOimg/EFI/BOOT
$ cat << 'EOF' > ./ISOimg/EFI/BOOT/grub.cfg
menuentry "mini Plamo on UEFI" {
  linux (cd0)/isolinux/vmlinuz-6.6.15-plamo64 root=/dev/ram0 rw net.ifnames=0 edd=off
  initrd (cd0)/isolinux/initramfs.tzst
}
EOF
$

ここまでの作業の結果として、ISOimg以下は以下のようなファイル構成になります。

$ find ISOimg/
ISOimg/
ISOimg/isolinux
ISOimg/isolinux/isolinux.bin
ISOimg/isolinux/ldlinux.c32
ISOimg/isolinux/vmlinuz-6.6.15-plamo64
ISOimg/isolinux/vmlinuz
ISOimg/isolinux/isolinux.cfg
ISOimg/isolinux/initramfs.tzst
ISOimg/EFI
ISOimg/EFI/BOOT
ISOimg/EFI/BOOT/grub.cfg
ISOimg/efiboot.img

UEFI対応のISOイメージを作成するにはxorrisofsにいくつか指定を追加する必要があります。追加したオプションは、-eltorito-alt-bootがEl Toritoの起動方法に代替がある指定で、-eltorito-platform efiはその代替環境はUEFIであり、その環境で起動する場合は"efiboot.img"を使う-eltorito-boot efiboot.img⁠、という意味になります。

$ xorrisofs -o uefi_test.iso  -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table \
  -eltorito-alt-boot -eltorito-platform efi -eltorito-boot efiboot.img ISOimg

こうして作ったISOイメージ(uefi_test.iso)は、VirtualBoxの[設定⁠⁠→⁠システム⁠⁠→⁠拡張機能]「EFIを有効化」した仮想環境でも正しくブートできました。

EFIを有効化したVirtualBoxでの起動
EFIを有効化したVirtualBoxでの起動

今回もずいぶん駆け足になってしまったものの、mini-Plamoのようなinitramfs環境の可能性を感じてもらえたでしょうか?

最近のOSは数千を越えるファイルやディレクトリから組み立てられた壮大な構築物ですが、initramfsを使えばそれらを1つのファイルに封じ込めることができ、カーネルやブートローダと言った少数のパーツと組み合わせるだけでDVDやUSBメモリといったさまざまな環境上で利用できます。

initramfsのこの特徴は、インストーラや起動時のモジュール組み込みのみならず、レスキューツールやキオスクPC、ファイルサーバ、ルータ/ブリッジといったさまざまな用途に応用できるでしょう。

用途や使い方が厳しく制限される商用ソフトウェアとは異なり、アイデアや工夫次第で無限の可能性が広がるのがOSSの魅力です。その魅力の一端でも読者の方に伝えることができれば幸いです。

おすすめ記事

記事・ニュース一覧