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

第53回Plamo Linuxの遊び方(その4)

いよいよ佳境に入ってきたこのシリーズ、今回からはインストーラ関連の話題を取り上げます。Plamo Linuxのインストーラは、HDD無しで動作する小さなLinux環境になっています。

Plamo Linuxインストーラの構成

筆者が公開しているPlamo Linuxのインストールメディアは3種のiso形式のイメージになっています。

$ ls -lh plamo-8.2*
-rw-r--r-- 1 root root 4.4G 11月 24日  11:24 plamo-8.2_x86_64_2023-11-24_dvd_01.iso
-rw-r--r-- 1 root root   73 11月 24日  11:24 plamo-8.2_x86_64_2023-11-24_dvd_01.iso.md5sum
-rw-r--r-- 1 root root 4.1G 11月 24日  11:26 plamo-8.2_x86_64_2023-11-24_dvd_02.iso
-rw-r--r-- 1 root root   73 11月 24日  11:26 plamo-8.2_x86_64_2023-11-24_dvd_02.iso.md5sum
-rw-r--r-- 1 root root  11G 11月 24日  11:30 plamo-8.2_x86_64_2023-11-24_usb.iso
-rw-r--r-- 1 root root   70 11月 24日  11:30 plamo-8.2_x86_64_2023-11-24_usb.iso.md5sum

isoイメージは3種類あるものの実体は1つで、usb.isoにはPlamo Linuxを構成する全パッケージとインストーラが含まれ、それをDVDサイズに収まるように二つに分けたのがdvd_01.isoとdvd_02.iso、dvd_01.isoインストーラとパッケージ群の前半部dvd_02.isoパッケージ群の後半部となっています。

Plamo-8.2は現在開発中で正式公開には至っていません。⁠2023-11-24⁠のような日付が入ったisoイメージは正式公開前のテスト版という位置付けになります。

さて、それではこのisoイメージの内部を眺めてみましょう。isoイメージはloopback形式でマウントすれば中身を見ることができます。

$ sudo mount plamo-8.2_x86_64_2023-11-24_dvd_01.iso /loop -o loop
[sudo] kojima のパスワード: xxxxx
mount: /loop: 警告: ソースは書き込み禁止です、読み込み専用でマウントします.
$ ls /loop
ChangeLog  EFI/  README  efiboot.img  isolinux/  plamo/  plamo-8.0  plamo-8.1  plamo-8.2

このうちisolinuxディレクトリ以下にあるのがインストーラとそれを起動するためのisolinux関連のファイルです。

$ ls -lh /loop/isolinux/
合計 260M
-rwxr-xr-x 1 root   root  4.6M  7月 11日  15:27 System.map-6.1.38-plamo64*
-rwxr-xr-x 1 root   root  212K  7月 11日  15:27 config-6.1.38-plamo64*
-rwxr-xr-x 2 root   root  8.6M  7月 11日  15:27 vmlinuz*
-rwxr-xr-x 2 root   root  8.6M  7月 11日  15:27 vmlinuz-6.1.38-plamo64*
-rw-r--r-- 1 kojima users 237M  7月 11日  17:55 initrd.gz

-r--r--r-- 1 kojima users 2.0K 11月 24日  11:22 boot.cat
-rw-r--r-- 1 kojima users  40K  7月 24日 2016年 isolinux.bin
-rw-r--r-- 1 kojima users  317  4月 19日 2022年 isolinux.cfg
-rw-r--r-- 1 kojima users 114K 10月 17日 2015年 ldlinux.c32
-rw-r--r-- 1 kojima users 179K 10月 17日 2015年 libcom32.c32
-rw-r--r-- 1 kojima users  24K 10月 17日 2015年 libutil.c32
-rw-r--r-- 1 kojima users  27K 10月 17日 2015年 vesamenu.c32
-rw-r--r-- 1 kojima users 120K  2月 24日 2009年 plamo41.lss
-rw-r--r-- 1 kojima users  98K  2月 19日 2016年 plamo61.lss
-rw-r--r-- 1 kojima users  323  2月 20日 2016年 sample.msg

前半の5つのファイルがインストーラで採用している6.1.38カーネルとインストーラ本体のinitrd.gzで、後半のファイル群はiso形式のメディアから起動するためのisolinuxが利用するファイルとなります。なお説明の都合上、上記lsの表示順序は修正しています。

“isolinux⁠とは、Linuxをさまざまなメディアから起動するために開発されているsyslinuxプロジェクトの一部で、CD-ROMやDVDといったiso形式のメディアから起動するためのブートローダを提供しています。syslinuxはMS-DOS/WindowsのFATファイルシステムからLinuxを起動するためのブートローダとして始まったものの、その後適用範囲を拡大し、iso形式のメディア(isolinux)やネットワークサーバ(pxelinux⁠⁠、Linux用パーティション(extlinux)等でも使えるブートローダになりました。

上記リスト中⁠vmlinuz⁠⁠vmlinuz-6.1.38-plamo64⁠はリンクカウント(2)が示すようにハードリンクされた同一のファイルです。なぜ同じファイルを2つの名前で参照しているのかと言うと、本来のiso形式ファイルシステムには「ファイル名長は⁠8+3⁠(8文字のファイル名と3文字の拡張子⁠⁠」という制限があるためです。この制限はOSのRockRidge拡張機能で回避できるものの、isolinuxはOSを介さずisoファイルシステムに直接アクセスするためファイル名長の制限を受けます。一方、インストーラに採用しているカーネルのバージョンは一目で分かるようにしておきたいため、1つのファイルを2つの名前で参照するようにしています。

これらファイルのうち、インストール用のPlamo Linux環境を構成するのが⁠initrd.gz⁠としてまとめているinitramfsファイルです。次にこのファイルの中身を調べてみましょう。

Plamo Linuxインストーラの内部構造

前回紹介したように、initramfsは複数のファイルやディレクトリをcpio形式のアーカイブ(書庫)化して圧縮しています。上記isolinux/にある⁠initrd.gz⁠は、⁠設定ファイル等の互換性のため)拡張子は⁠.gz⁠なものの、実際はzstdで圧縮しているので展開には以下のようなコマンドを使います。なお、cpioで指定している-ivdオプションの意味は、⁠-i⁠「展開⁠⁠、⁠-v⁠「詳細表示⁠⁠、⁠-d⁠「ディレクトリ作成」となります。

$ file /loop/isolinux/initrd.gz 
/loop/isolinux/initrd.gz: Zstandard compressed data (v0.8+), Dictionary ID: None
$ zstd -dc /loop/isolinux/initrd.gz | cpio -ivd
cdrom
var
var/local
...
run/utmp
tmp
1413569 ブロック
$  ls -F
bin/   cdrom/  etc/   init@  lib64/  mnt/   root/  sbin/  tmp/  var/
boot/  dev/    home/  lib/   media/  proc/  run/   sys/   usr/

前回取りあげたモジュール組み込み専用のinitramfsとは異なり、インストーラ用のinitramfsは独立して動作するシステム一式、すなわちPlamo Linuxのカテゴリーで言うとシステム運用に必須の⁠00_minimum⁠を元に、opensshやparted、XFS、NFS、Python等のパッケージを追加した環境になっています。

$ ls -F ./bin
[*                   date*           gzexe*     lzma@           pwd*      umount@
bash*                dd*             gzip*      mk_cmds*        pwdx*     uname*
btrfs*               df*             head*      mkdir*          rm*       uncompress*
...
$ ls -F ./lib
cracklib/                            libdl.so.2@             libpam_misc.so.0@
device-mapper/                       libfdisk.so.1@          libpam_misc.so.0.82.1*
firmware/                            libfdisk.so.1.1.0*      libpamc.so.0@
ld-2.33.so*                          libhandle.a             libpamc.so.0.82.1*
...

この環境は独立して動作可能なので、⁠chroot⁠すればその環境内のコマンドやライブラリで動作します。以下、このchrootした環境を「ゲスト環境」と呼び、操作時のプロンプトは⁠#⁠で区別します。

$ sudo chroot .
[sudo] kojima のパスワード: xxxx
# pwd
/
# ls
bin/   cdrom/  etc/   init@  lib64/  mnt/   root/  sbin/  tmp/  var/
boot/  dev/    home/  lib/   media/  proc/  run/   sys/   usr/

ゲスト環境にはインストーラに必要な最低限のパッケージしか用意していないものの、きちんと動作するPlamo Linux環境なので、お好みのパッケージを追加してカスタマイズすることが可能です。

インストーラのカスタマイズ

インストーラを改造する一例として、デフォルトでは入っていないemacsエディタを追加してみましょう。

# emacs
bash: emacs: コマンドが見つかりません
# emacs_mini
bash: emacs_mini: コマンドが見つかりません

Plamo LinuxのCUI(非ウィンドウ)用のemacsは01_minimum/以下の⁠emacs_{bin,lib,mini}⁠の3つのパッケージとして提供しているので、まずはこれら3つのパッケージをゲスト環境内に持ち込まないといけません。chrootしたゲスト環境内からはホスト側のファイルやディレクトリを直接参照できないため、ゲスト環境内にパッケージを持ち込むためには、ホスト側からゲスト環境のディレクトリへパッケージをコピーしたり、ゲスト側からwgetやscpを使ってネットワーク的に入手する等、いくつかの方法があるものの、今回はバインド・マウントを使ってゲスト内からもホスト側のisoイメージを利用できるようにしてみます。

“バインド・マウント⁠とはmountコマンドを⁠--bind⁠オプションを使って実行し、あるディレクトリを別のディレクトリに結びつける機能です。

ホスト側のisoイメージはloopback経由で/loopにマウントしているので、これをインストーラ内のcdromディレクトリにバインド・マウントします。ついでにゲスト側からもシステム情報が見れるように/sysディレクトリ等もバインド・マウントしておきましょう。

バインド・マウントはホスト側での作業になります。以下の実行例では、プロンプトが⁠$⁠になっているのがホスト側の作業、⁠#⁠になっているのがゲスト側の作業です。

# exit
$ sudo mount --bind /loop ./cdrom
$ sudo mount --bind /sys ./sys
$ sudo mount --bind /dev ./dev
$ sudo mount --bind /proc ./proc

以上でゲスト側からもホスト側のDVDファイル(実体はloopbackマウントしたisoファイル)を参照できるようになったので、再度ゲスト環境にchrootします。

$ sudo chroot .
# df -h
ファイルシス   1K-ブロック    使用   使用可 使用% マウント位置
/dev/loop0       4.4G  4.4G     0  100% /cdrom
devtmpfs          31G     0   31G    0% /dev
# ls /cdrom
ChangeLog  EFI/  README  efiboot.img  isolinux/  plamo/  plamo-8.0  plamo-8.1  plamo-8.2
# ls /cdrom/plamo/01_minimum/emacs*
/cdrom/plamo/01_minimum/emacs_bin-28.2-x86_64-B2.tzst
/cdrom/plamo/01_minimum/emacs_lib-28.2-x86_64-B2.tzst
/cdrom/plamo/01_minimum/emacs_mini-28.2-x86_64-B2.tzst

こうしておけばゲスト環境からもisoイメージを利用でき、installpkgを使って必要なパッケージをインストールできます。以下の実行例では、最後に⁠check-update-cacheが無い⁠⁠、旨のエラーが出ているものの、この処理はデスクトップ環境用なので無視して問題ありません。

# installpkg /cdrom/plamo/01_minimum/emacs*
emacs_bin-28.2-x86_64-B2([required]) のインストール中
PACKAGE DESCRIPTION:
emacs_bin: Emacs用ツール
emacs_bin:
emacs_bin: emacsが利用する各種ツール
...
processing [ emacs_lib ] ...
./var/log/initpkg/emacs_lib: line 2: check-update-cache: not found
./var/log/initpkg/emacs_lib: line 3: check-update-cache: not found

Plamo LinuxのCUI用emacsは⁠emacs_mini⁠というコマンド名になっています。動くかどうか試してみましょう。

# emacs_mini
emacs_mini: /lib/libc.so.6: version `GLIBC_2.34' not found (required by emacs_mini)

おっとしまった、ゲスト環境(インストーラ)はPlamo-7.xを元に作っていたので、glibcが2.33のままでした。この場合「2.34の壁問題」があり、Plamo-8.x用のパッケージは動きません。

ついでなので、ゲスト環境のglibcもPlamo-8.x用の2.38に更新しましょう。このバージョンのglibcではlibcrypt回りの機能がlibxcriptパッケージに分離されたので、そちらも合わせてインストールしておきます。

# updatepkg /cdrom/plamo/00_base/glibc-2.38-x86_64-B3.tzst
removing glibc-2.33

Removing package glibc...
Removing files:
  --> Deleting symlink lib/ld-linux-x86-64.so.2
...
# installpkg /cdrom/plamo/00_base/libxcrypt-4.4.36-x86_64-B2.tzst
libxcrypt-4.4.36-x86_64-B2([required]) のインストール中
PACKAGE DESCRIPTION:
libxcrypt: xcryptライブラリ
libxcrypt:   
libxcrypt: 従来はglibcが対応していたcrypt回りの機能を独立させたライブラ
libxcrypt: リ。PAM等が使うため必須
...

これらを更新したところ、ゲスト環境内でも無事emacsが使えるようになりました。

図1 ゲスト環境内で動作するemacs
ゲスト環境内で動作するemacs

なお、glibcパッケージはインストール後に環境の初期化処理を行い、その際にhostnameコマンドでホスト名を設定します。手元で試したところ、ゲスト側でglibcをアップデートしてホスト名を更新すると、ホスト側のホスト名も変ってしまい、ホスト側のXクライアントが正しく利用できない($DISPLAYがわからなくなる)現象が見られました。この問題はホスト側で⁠hostname -F /etc/hostname⁠してホスト名を復旧すれば解決します。このあたり、chrootだとコンテナほどにはネームスペースをきちんと分離できていないことが原因だろうな、と思っています。

さて、こうしてゲスト環境内でemacsが使えるようになったものの、この結果を本来のインストーラに反映させるためには、emacsを追加したゲスト環境を含むinitramfsを作り直し、それを組み込んだisoイメージを作成する、という作業が必要になります。

ブート可能なisoイメージの作成は結構面倒な作業なので回を改めることにして、今回はemacsを追加したゲスト環境をinitramfs化してブートするところまでを紹介しましょう。

chroot環境のinitramfs化

まずはemacsをインストールしたゲスト環境をinitramfsに固めます。その際にはホスト側のファイル類を参照してしまわないよう、バインド・マウントは忘れずに解除しておきます。

# exit
$ sudo umount ./cdrom
$ sudo umount ./proc
$ sudo umount ./sys
$ sudo umount ./dev

また、今回はインストーラの⁠isolinux/initrd.gz⁠を一般ユーザ権限で展開したため、ファイルやディレクトリの所有者情報を正しく継承できていません。そのためちょっと乱暴ですが、initramfs用のファイルやディレクトリの所有者を全てrootにしておきます。また、この先の作業はroot権限が必要になるため、⁠su⁠して作業を進めます。

$ su
パスワード:xxxx
# chown -R root:root *

initramfsはcpio形式の書庫ファイルを圧縮したものなのでcpiozstdで作ります。cpioはファイル名を入力にとり、それらを連続して1つの書庫ファイルにまとめるので、あるディレクトリ以下全てのファイルを対象にするにはfindと組み合わせるのが便利です。

# find . -print | cpio -ov -Hnewc | zstd -9 > ../new_initramfs.zstd
.
./cdrom
./var
./var/local
./var/local/la-files
./var/local/la-files/mod-gltex.la
...
./tmp
1741736 ブロック
#

上記コマンドのうち、最初の⁠find .-print⁠は現在のディレクトリ以下に存在する全てのファイルとディレクトリの名前を標準出力に書き出します。次の⁠cpio -ov-Hnewc⁠は、標準入力経由でfindからの出力を受け取り、各ファイルを書庫ファイルの形式にして標準出力に書き出します。

“-Hnewc⁠はフォーマット(書庫形式)の指定で、⁠newc⁠⁠SVR4 portable format⁠を意味します。cpioは長い歴史を持つアーカイブ用ソフトウェアのため古くから使われているさまざまな形式に対応していますが、よほど古い環境との互換性を求めない限り、⁠newc⁠を指定しておくのが無難です。

標準出力に書き出された書庫ファイルは⁠zstd -9⁠で圧縮され、ひとつ上のディレクトリの⁠new_initramfs.zstd⁠というファイルに保存されます。zstdは圧縮率を⁠-1⁠から⁠-19⁠の範囲で指定でき、数字が大きくなるほど圧縮率が高くなってファイルサイズは小さくなるものの、圧縮に時間がかかるようになります。手元であれこれ試したところ、⁠-9⁠くらいが圧縮率と圧縮速度のバランスがいい感じでした。

さて、カーネル(vmlinuz-6.1.38-plamo64)とこうして作成した⁠new_initramfs.zstd⁠を読み込めば、Plamo Linux用の改造したインストーラとなります。実用的にはUSBメモリやDVDから起動すべきものの、そのあたりの話題は次回として、ここでは既存のgrubを使って手動で立ちあげてみることにしましょう。

そのために⁠new_initramfs.zstd⁠を/bootディレクトリに移し、grubのコマンドモードを用いて、同じディレクトリにあるカーネルと共に読み込みます。

図2 GRUBのコマンド画面
GRUBのコマンド画面

上図はスクリーンキャプチャで小さいため補足すると、grubのメニュー画面から⁠c⁠でコマンドモードに移り、⁠ls⁠で利用可能なパーティションを確認、(hd0,gpt2)/boot/以下にカーネルと新しく作ったinitramfsが見えるので、以下のコマンドでカーネルとinitramfsを読み込み、"boot"で起動しています。

grub> linux (hd0,gpt2)/boot/vmlinuz-6.1.38-plamo64 root=/dev/ram0 rw
grub> initrd (hd0,gpt2)/boot/new_initramfs.zstd

こうして起動した改造版のインストーラでは、新たにインストールしたemacs_miniも起動できました。

図3 改造版インストーラで起動し、emacs_miniを実行
改造版インストーラで起動しemacs_miniを実行

今回はPlamo Linuxのisoイメージからインストーラを取り出して改造し、initramfsにまとめ直してシステムを起動する作業を紹介しました。

見てきたように、現在使っているインストーラはPlamo-7.x時代から流用しているため、あちこちに齟齬が生じています。そこで次回は、0から新たにインストーラ用のinitramfsを作成し、DVDやUSBメモリから起動できるisoイメージを作ってみます。

おすすめ記事

記事・ニュース一覧