安裝 Gentoo 時將 /usr 放在獨立分割區需要新方法

這是今年初幫實驗室裝新 server 的時候注意到的,當時一整個沒空加上很懶,就沒有去深入研究。
所以當時索性把 /usr 直接放在 / 分割區,也不算真的去解決了這個問題。
現在已經成為了上班族,下班時間就做自己有興趣的事,時間分割得很開,和學生時代不一樣了。
最近突然想起這個問題,於是就去租了一個月的 KVM VPS 來實驗看看當時沒解決的問題。

首先要先說到 emerge --sync 後再打 eselect news list 會看到的列表:

News items:
[1] 2009-04-18 Generation 1 Java Setup Deprecated
[2] 2010-03-25 Python 3.1
[3] 2010-08-01 (2010-08-01-as-needed-default - removed?)
[4] 2012-03-16 (2012-03-16-udev-181-unmasking - removed?)
[5] 2012-05-21 Portage config-protect-if-modified default
[6] 2012-09-09 make.conf and make.profile move
[7] 2012-11-06 PYTHON_TARGETS deployment
[8] 2013-01-23 (2013-01-23-udev-upgrade - removed?)
[9] 2013-02-10 New 13.0 profiles and deprecation of 10.0 profiles
[10] 2013-03-29 Upgrading udev to version >=200
[11] 2013-06-07 Portage preserve-libs default
[12] 2013-06-30 Printer browsing in net-print/cups-1.6
[13] 2013-08-23 Language of messages in emerge logs and output
[14] 2013-09-27 Separate /usr on Linux requires initramfs

年初遇上 /usr 放在獨立分割區無法開機時,恰巧是 1/24,也就是在 [8] 被移除掉的那一則 news。
內文是這樣:

Title Upgrading udev from 171 (or older) to 197
Author Samuli Suominen
Posted 2013-01-23
Revision 1

Upgrading udev from 171 (or older) to 197 will require special attention:

- Remove udev-postmount from runlevels.

- The need of CONFIG_DEVTMPFS=y in the kernel; need to verify the fstype for
possible /dev line in /etc/fstab is devtmpfs (and not, for example, tmpfs)

- The case of predictable network interface names; if the file
/etc/udev/rules.d/70-persistent-net.rules is being used for renaming
network interface names to already existing names, then you need to
read following bug[1] because it's no longer possible. This won't
be a problem with the new predictable network interface name scheme[2].

[1] http://bugs.gentoo.org/453494
[2] http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames

- Support for older kernels than 2.6.39 is dropped. If you need older kernel
we recommend you to look into sys-fs/eudev or use local overlay for keeping
the old ebuild. Remember to also get the distfiles where the patchsets are.
The upgrade into current stable version of gentoo-sources is recommended.

- The case of separate /usr; if it worked for you with 171 it will continue
to work for you with 197. We still recommend initramfs with separate /usr
mounting capabilities because you might need packages like sys-apps/kbd
(keymaps in /usr) or net-wireless/bluez (possible keyboard) in early boot.

And read every message printed by the emerge of udev and udev-init-scripts
to ensure the system is in order before booting as this news item might
not be complete.

Apologies if this news came too late for you.

當時 Gentoo 各方面的文件還未完善,相關的資料很少。
最與問題核心的就是這篇:Early Userspace Mounting
還有查到不少關於這項激進修改的論戰,但現在都已經不重要了。
總之就是想要把 /usr 放在獨立分割區的話,那麼就得手工製作一個 initramfs,把 /usr 給弄進去。
但操作過程就比較麻煩,當時也沒打算在學校久留,就沒有繼續解決這個問題。

這次安裝 Gentoo,在 chroot 環境下做完最初次的 emerge --sync 後,就在 eselect news list 裡看到了 [14] 這項:

2013-09-27-initramfs-required
Title Separate /usr on Linux requires initramfs
Author William Hubbs
Posted 2013-09-27
Revision 1

Linux systems which have / and /usr on separate file systems but do not
use an initramfs will not be supported starting on 01-Nov-2013.

If you have / and /usr on separate file systems and you are not
currently using an initramfs, you must set one up before this date.
Otherwise, at some point on or after this date, upgrading packages
will make your system unbootable.

For more information on setting up an initramfs, see this URL:

https://wiki.gentoo.org/wiki/Initramfs/HOWTO

Due to many upstream changes, properly supporting Linux systems that
have /usr missing at boot time has become increasingly difficult.
Despite all our efforts, it already breaks in some exotic
configurations, and this trend is likely to grow worse.

For more information on the upstream changes and why using an initramfs
is the cleanest route forward, see the following URLs:

http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
https://blog.flameeyes.eu/2013/01/the-boot-process

很顯然,有關的配套措施和自動化解決方案已經成形,不再需要手動進行 initramfs 的製作就能簡單將 /usr 給弄進去。
上面的關鍵網址就是 Initramfs/HOWTO 這一頁,只要簡單輸入一行 genkernel --install --no-ramdisk-modules initramfs,精美的 initramfs 就會自動出現在 /boot 下面了。
以我最近實驗的 3.11.2-gentoo 版 kernel 為例,產生出來的就是 /boot/initramfs-genkernel-x86_64-3.11.2-gentoo。
當然對於不愛用 genkernel 來做 kernel 的人,看到 genkernel 這字一定會反感,但是在這行指令的上方就有說明了:

Gentoo's kernel building utility, genkernel, can be used to generate an initramfs, even if you didn't use genkernel to configure and build your kernel.

所以就放心打下去吧。

至於 kernel 的製作,我用的還是老方法,去 /usr/src/linux 裡打 make menuconfig 慢慢選。
選完就 make; make modules_install,再把生出來的 arch/x86_64/boot/bzImage 複製到 /boot 去就行了。
不過因為這次我開始試著使用 GRUB2 安裝,所以 kernel 的檔案命名也要注意。
我是取成 vmlinuz-3.11.2-gentoo,這樣我下 grub2-mkconfig -o /boot/grub/grub.cfg 時就能自動抓到。

GRUB2 詳細的操作方式可以參考這頁:GRUB2
因為 VPS 的 BIOS 不是 EFI BIOS,但是我卻使用 GPT,所以採用的是 BIOS/GPT 這種玩法。
不過現在用這種玩法必須在執行 grub2-install /dev/sda 時多下一個 --force 參數才行,否則 GRUB2 會禁止你這樣做。
另外,在安裝 GRUB2 的時候,GRUB_PLATFORMS 這環境變數還是建議設一下。
雖然上面的網頁說它會自動猜,但太相信這東西的話在某些場合會遇到麻煩。

一旦上了新的 udev,最前面的 news 提到的這個連結說的事也會發生:PredictableNetworkInterfaceNames
舉例來說,我這台 VPS 的網卡代號不再是 eth0,而是變成了 enp0s3。

以下題外話。

現在這間公司和我之前想的一樣,使用的 OS 除了 RedHat 就是 CentOS。
實驗室的學長進去以後似乎帶起了 Ubuntu 使用的風潮,但真正適合系統軟體工程師的除了 Gentoo 外其實別無選擇,畢竟 portage 和 apt、yum 是完全不同的面向。
我從很久以前就常在說,看一間公司用什麼 Linux distibution 開發 Linux 程式,就能概略評估出那家公司工程師的平均程度。
Gentoo 的套件系統可說是完全面向工程師量身打造設計的,真正的工程師一旦接觸過 portage,就不可能再接受 portage 以外的套件系統。

如果一個系統軟體工程師曾經接觸過 portage 而放棄了它,那麼我會認為他要不就是沒有實力只適合去開發應用軟體,要不就是懶到極點。
如果一個網管人員曾經接觸過 portage 而放棄了它,那麼我會認為他果然只是一個普通的網管,很盡責地在學習他本分內的東西,所以正常。

雖然說選用什麼 distribution 長年來都是頗具爭議的一件事,很多人為了避免引戰也會假裝中肯說這是看個人喜好...
為了面對一些只適合使用 RedHat 或 CentOS 的客戶,在封裝和測試階段使用這些 distributions 無可厚非。
但是 Gentoo 的使用客群是十分的明確,明確到簡直霸道的地步,其使用者歧視其它 distributions 的使用者也是家常便飯的事。
當然我也得替其它 distributions 的使用者說點公道話,對於一般網管或只是將 Linux 拿來當 desktop 環境用的一般使用者來說,那些傻瓜型的套件系統的確是方便多了。
以 Debian 家族來說,它也是有提供 source package 這個機制來讓你達成和 portage 相同程度的自訂能力,但相關的操作方式和便利性,跟被打回史前時代差不多。
一旦這些使用者吃過 source package 的虧,受過 source package 的苦,一旦接觸到 portage,自然而然也會投入 Gentoo 的陣營,除非他們是有什麼特殊的信仰。
和 FreeBSD 的 ports 一樣,Gentoo 的 portage 也會遇到地雷,source code 編譯不過,library 連結失敗,這些都不是一般使用者可以處理的。
但是對於有點程度的系統軟體工程師來說,解決那些問題都只是彈指之間的事而已,會對此感到懼怕的人是不配當系統軟體工程師的。

從很久以前就一直陸續有人問我,Linux 的套件和函式庫成百上千,為什麼我都知道什麼東西是幹什麼用的。
甚至曾經有個 10 歲出頭的小鬼說我能知道這麼多只不過是因為我年紀比較大,等他跟當時的我一樣大就會知道得比我多了。
但是等到他也 20 歲的時候,他還是發現自己什麼都不知道,明明也玩了快 10 年的 Linux 也寫了快 10 年的程式,但卻沒有獲得和我相同的能力。
我只能說這是理所當然的,因為我和他之間在起跑點開始所身處的環境就不一樣,因為我用的是 FreeBSD。
對他來說,裝個 apache 的動作就不過是一行安裝指令,安裝完以後的心得就是 apache 裝完了。
但是我在安裝時眼睛看到的卻是:

對他來說,安裝個 bind 來管理 DNS records,敲完安裝指令後,心得不過就是 bind 裝完了。
但是我在安裝時眼睛看到的卻是這樣:

諸如此類,同樣是安裝東西,但我看到的名詞就遠比他多得太多了。
多年來我升級和安裝新系統的次數早已多到數不清,這些名詞反覆出現在我的眼前到一次又一次地激發我的好奇心。
而這最終的結果,就是我漸漸變得知道那些東西是幹什麼用的,以及如何利用它們來做什麼事,而他始終得到的就是類似「xxx 裝完了」這樣的心得。
當然,在編輯 .conf 檔設定各種程式的行為時,他多少也會見到一些名詞,但就廣度來說仍然不夠。
而且安裝新機器或升級套件,那些 .conf 檔大都也是不太需要重新編輯,甚至可以直接複製舊的來用,接觸到各式各樣名詞的機率又更低了,更甭說到激發好奇心讓他去探究的程度。
其實我知道的東西沒有那些人想像得多,會知道一些東西只不過是碰巧看到,然後好奇去研究的。
只是這個碰巧的機率在 FreeBSD 這樣的環境下實在太高,所以也造就了我懂得比別人多懂了一些東西的結果。
像是有人問我,為什麼我知道處理 Unicode 可以用 ICU 這套 library,是我讀了什麼書或是誰告訴我的嗎?
如果我回答「因為我裝了 boost」或是「因為我用 FreeBSD」,一定有人覺得我這回答很跳躍或是不想認真回答吧?
然而事實擺在眼前:

Gentoo 承襲著 FreeBSD 這一優良的環境,所以就算被迫在 Linux 環境工作,我選擇的 distribution 會是最接近 FreeBSD 的 Gentoo。

身為一名以促進世界進步為主要訴求和理想的人,我不會去建議一個 programmer 在工作上去用 Gentoo 以外的 Linux distributions。
當然如果他是在自己家或者辦公用的電腦上裝 Ubuntu 或其它 distributions,我倒是覺得沒什麼關係。
為什麼我會堅持到接近偏執的地步?如果你是個 C++ programmer,去看看你標準套件系統上的 boost 能裝到哪一版就會知道了。
當然一定會有人想吵說這些東西可以在自己 $HOME 下手動裝一份就好,但請摸著自己良心好好想想,如果今天系統上就有提供,我需要花這時間自己裝一份嗎?
特別是很多 programmer 在同一台 server 上工作,你要他們去各自 build 一份 library 在自己目錄浪費空間,或者是要他們去 link 其它使用者 $HOME 下的東西?
library 是不是放在系統路徑下,其便利性也是有差別的,很多時候還需要調整 Makefile 的設計才能正常動作,這只會造成團隊開發的麻煩而已。
也許有人會說那就用舊版的 library 就好了,用這麼新的幹嘛,萬一有 bug 怎麼辦?
其實 portage 也提供套件 downgrade 的做法,指定版號就能降級下去了,真遇到問題懶得替開放原始碼社群做點貢獻的話,降級一下也還是夠新。
而且降級也是要看降了多少級,如果降到跟別家 distributions 提供的一樣舊,那選用 Gentoo 的意義就失去了一大半。
真的遇到這麼糟糕的狀況,我會選擇的是去克服問題,或者回報這個問題並且討論解決的方式。
當然,因為我是程式開發人員,這樣的態度也比較侷限於遇到 library 方面的問題時才會採取。
至於系統運作層面的東西,那就是交給網管型的 hacker 們去貢獻解決方案 (譬如 udev 或 grub2 之類的問題)。
術業有專攻,每個人並不需要強迫自己在每一處都要有所貢獻,除非是因為某些個人理念,否則這樣做也只是在沽名釣譽而已。