「何か」を探す
ふと疑問に思いました。ArchLinuxをインストールするとき、ディレクトリ構造って「何によって」作られているんでしょうか?
いままでUbuntuやDebianなどを使ってきましたが、インストーラーにシステム構築過程を任せてLinuxをインストールしてきた身としては、さっぱりわかりません。
あまり役に立たないかもしれませんが、今回は「ArchLinuxをインストールするときディレクトリ構造はどう作られているか」を追ってみました。
何回か環境をもとに戻す必要がありそうなので調査にはVirtualBoxを使いました。
Arch Linux をダウンロード
https://www.archlinuxjp.org/download/
にてダウンロードしたisoにて仮想マシンを立ち上げて、isoの環境にて調査を行っています。(root@archisoの状態)
憶測
archのインストールガイドにそってインストールを進めると、「ベースシステムのインストール」と称して、pacstrapなるスクリプトを使うように書かれています。
これは必要最小限のパッケージをインストールするためのスクリプトです。
このpacstrapを使う前に、パーティションを作ってファイルシステムを作ったストレージを/mntにマウントするように指示があります。
あたりまえですが、このマウントした時点では、/mnt以下に何も(bootディレクトリを作った以外は)ディレクトリが存在しません。
そしてpacstrapを実行した後には、/mnt以下に FHS(ファイルシステム階層標準)に準拠(しているであろう)ディレクトリ構造が出来上がっています。
pacstrapを確認
ということはpacstrapにおいてディレクトリ構造がつくられているのかな?と思いソースコードを確認してみました。
pacstrap
https://git.archlinux.org/arch-install-scripts.git/tree/pacstrap.in
ディレクトリをつくっているであろう箇所は以下の部位です。
# create obligatory directories
msg 'Creating install root at %s' "$newroot"
mkdir -m 0755 -p "$newroot"/var/{cache/pacman/pkg,lib/pacman,log} "$newroot"/{dev,run,etc}
mkdir -m 1777 -p "$newroot"/tmp
mkdir -m 0555 -p "$newroot"/{sys,proc}
ここではvar、dev、run、etc、sys、procなどをmkdirでつくっています。
でも、 FHS(ファイルシステム階層標準)にある必須(であろう)ディレクトリ全部ではないですね。
このシェルスクリプトの中には他にディレクトリを作っているような記述はありません。ですのでこのソースには書かれていない他の「何か」によってディレクトリ構造が作られているようなのです。
うーむ一体「何が」???
pacstrapでのディレクトリ作成後
そこでこのディレクトリ作成の後の記述を追ってみることにしました。
ここです。
msg 'Installing packages to %s' "$newroot"
if ! pacman -r "$newroot" -Sy "${pacman_args[@]}"; then
die 'Failed to install packages to new root'
fi
条件式にはなっていますが、ArchLinuxのパッケージマネージメントツールであるpacmanによって何やらをインストールする記述のようです。
pacstrapにはbaseもしくはbase-develを引数として実行することになるかと思います。 base、base-develともにパッケージグループの名称で、それぞれのグループには数十個のパッケージがあります。
baseと指定しただけでその数十個のパッケージをインストールすることができるようになっているんですね。
で、 pacstrapの引数として渡したbaseもしくはbase-develはこのコードの ${pacman_args[@]}に入ってpacmanコマンドに渡されるわけなのです。
また $newrootには pacstrapで指定した/mntが入っています。
つまり通常であれば
pacman -r /mnt -Sy base
や
pacman -r /mnt -Sy base base-devel
をこの箇所で実行していることになります。条件式になっているのは、何らかの理由でこの行が失敗した場合エラーが返るのでそれを捉えてエラー文を出力するようになっているためです。
pacstrapにはオプションの設定がされていますが、もし何もオプションをつけないことを考えると pacstrapで実行されているのは以下の部分になると思います。
[[ -d $newroot ]] || die "%s is not a directory" "$newroot"
if ! mountpoint -q "$newroot" && (( ! directory )); then
die '%s is not a mountpoint!' "$newroot"
fi
# create obligatory directories
msg 'Creating install root at %s' "$newroot"
mkdir -m 0755 -p "$newroot"/var/{cache/pacman/pkg,lib/pacman,log} "$newroot"/{dev,run,etc}
mkdir -m 1777 -p "$newroot"/tmp
mkdir -m 0555 -p "$newroot"/{sys,proc}
# mount API filesystems
chroot_setup "$newroot" || die "failed to setup chroot %s" "$newroot"
msg 'Installing packages to %s' "$newroot"
if ! pacman -r "$newroot" -Sy "${pacman_args[@]}"; then
die 'Failed to install packages to new root'
fi
手動検証
そこでこのコードを手動でシェル上で打ってみてどうなるかを確かめてみました。
(検証のために仮想マシンのハードディスクをまっさらにしてから、再度パーティションやファイルシステムをつくりマウントし直しています)
まずはこれ
root@archiso mkdir -m 0755 -p "$newroot"/var/{cache/pacman/pkg,lib/pacman,log} "$newroot"/{dev,run,etc}
root@archiso mkdir -m 1777 -p "$newroot"/tmp
root@archiso mkdir -m 0555 -p "$newroot"/{sys,proc}
いろいろ試行錯誤しているうちに、とりあえず
root@archiso mkdir -m 0755 -p "$newroot"/var/lib/pacman
だけをやっておけば後のpacman実行にエラーが出ないことがわかりました。
また chroot_setup "$newroot"
はコマンドラインで実行ができない(そんなコマンド無いと怒られた)ので無視しました。
ですので最終的にpacstrapの手動テスト実行はこの2行だけになりました。
root@archiso mkdir -m 0755 -p "$newroot"/var/lib/pacman
root@archiso pacman -r /mnt -Sy base
さてこれらを実行してみると…
テッテレー!!
ディレクトリ構造ができていますね…。
ということは
pacman -r /mnt -Sy base
において何らかの処理がされていると考えたほうがよさそうです。
しかしpacmanは基本的にパッケージをインストールするコマンドです。いろいろ調べてみましたがディレクトリを作る機能など見当たりません。
ということはインストールされるパッケージになにか秘密があるのでしょうか?
baseパッケージグループに属しているパッケージを調べてみることにしました。
baseパッケージグループ
https://www.archlinuxjp.org/groups/x86_64/base/
この記事を書いている時点では56のパッケージが登録されています。
上記ページをつらつら眺めていたのですが、気になるパッケージがありました。
filesystem
です。
filesystemってfatとかext4とかのあれのことですかね?
でも説明文を見ると
Base filesystem
とあります。どうも fatとかext4とかのファイルシステムとは別なもののようです。
うーむ怪しい。
そこでこのfilesystem「だけ」をインストールすることにしてみました。
(検証のために仮想マシンのハードディスクをまっさらにしてから、再度パーティションやファイルシステムをつくりマウントし直しています)
再度
root@archiso mkdir -m 0755 -p "$newroot"/var/lib/pacman
を実行して今度は
pacman -r /mnt -Sy filesystem
です。
どうでしょう?
テッテレー!!
ディレクトリ構造出来上がっとる!!
このパッケージがディレクトリ構造を作っていた「何か」だったんですね。
順番
でも先にこのfilesystemがインストールされないとディレクトリ構造ができないわけですから、binやsbinに収まるべきバイナリインストールするパッケージよりも先にインストールされていないといけないですよね。
順番ってどうやって制御しているだろう?
試しにfilesystemを入れずに、ほかのパッケージだけをインストールしてみることにしてみました。
(検証のために仮想マシンのハードディスクをまっさらにしてから、再度パーティションやファイルシステムをつくりマウントし直しています)
再度
root@archiso mkdir -m 0755 -p "$newroot"/var/lib/pacman
を実行して今度は
pacman -r /mnt -Sy coreutils
としてみました。インストールするパッケージは何でもよかったのですが coreutilsにしてみました。これならLinuxに必要なコマンド群のパッケージですからね。
実行してみるとはたと気が付きました。 coreutilsの依存パッケージにfilesystemがいるじゃないですか。
つまり coreutils がインストールされる前には filesystemがインストールされるわけですね。
どうやら大元はglibcの依存パッケージとして filesystemがあるので、 glibcに依存しているパッケージは間接的に filesystemに依存していることになるようです。baseに属しているパッケージはほとんどがglibcに依存しています。
ですのでglibcがインストールされる段階で filesystemがインストールされ、ディレクトリ構造が作り上げられます。
そしてそこにさまざまなパッケージがインストールされていくという仕組みになっているようです。
うまいことになっていますな。
おまけ
ちなみに filesystemのソースコードを見るとどのようにディレクトリが作られているかがわかります。
filesystem
https://git.archlinux.org/svntogit/packages.git/tree/trunk/PKGBUILD?h=packages/filesystem
ちなみにGentooLinuxではシェルスクリプトでディレクトリ構造をつくるようです。ArchLinuxのfilesystemパッケージも結局中身はシェルスクリプトのようなので、ディレクトリ構造はシェルスクリプトで作るのが基本なんですね。
勉強になりました。