有很多單位的 FreeBSD server 仍然都保持在 FreeBSD 4.x,主要的原因包括了:
- 4.x 的 performance 比 5.4 好:包括了 SMP、I/O、blah blah... 效率不彰的其中一個原因是因為有很多 kernel code 重新改寫,還沒有經過調校 (像是邏輯上的錯誤造成多跑幾個迴圈,CPU time 多吃了一些但不會因此當機的情況),這方面比起 4.x 所花的時間少太多。
- 5.x 的系統不穩定:在 5.0 剛出來的時候幾乎是「不能用」的狀態,對一般的電腦每天當個兩次也許沒什麼,但對 server...。這個情況在 5.3 的時候有了改善,但直到 5.4 之後才穩定下來。
但上面所說的這兩點在 6.0 有了變化:
- 6.x 的 performance 比起 5.x 好太多,主要幾個原因包括了 Giant lock code 愈來愈少、調校了不少子系統,同時,在單 CPU 的機器上比起 4.x 已經差不多。而 6.x 的 Kernel-threading 效率則是超越了 4.x 的 Userland-threading,這點使得不少使用 Thread 的程式受益。
- 6.x 系統的穩定度已經獲得大幅改善,目前已知的問題裡只剩下 ata driver 比較大,但目前在 6.1-PRERELEASE 已經在處理,所以,6.1-RELEASE 會解決。
基於這些理由,有不少人願意嘗試 FreeBSD 6.x。如果是重新安裝當然沒問題,但也有已經安裝好的機器,裡面的資料不方便備份再重灌,而且這些機器並不是很容易接觸到 console (機器在國外,或是進機房需要蓋二三十個章之類的...),這會使得升級上會產生困難,於是就有些人想要搞 remote upgrade for major version changing...
由於 remote upgrade 整個難度在於需要 single user mode 操作的部分,雖然依照官方的說法,4.x to 5.4 與 5.4 to 6.x 都需要 single user mode,但實際上 5.4 to 6.x 可以先從別台抓 6.0 的 libc.so.6
與 libm.so.4
再直接升級 (聽起來很 dirty,不過可以動),所以整個難度在於 4.x to 5.4。
另外一個需要注意的是建議先升級到 4.11 再處理。我曾經試過一台 4.8 要直接跳到 5.4 的,發現在 mergemaster
的地方一直失敗,最後直接到 console 前,在 single user mode 後 make installworld
裝入新的 mergemaster
...
至於為什麼會選擇升級到 5.4 (RELENG_5_4
) 而不選 5.x (RELENG_5
),這是因為 5.x 這陣子在準備 5.5-PRERELEASE,有不少東西改來改去的,遇到時間點不對的情況 checkout 出來的 code 會使得系統爛掉,所以找個確定可以用的版本會比較好。
以下是我從 4.x 升級到 5.4 的方法,主要是參考 5.4 的 /usr/src/UPDATING
,以及我之前寫的 遠端從 4.7-x 升級到 5.0-RELEASE 這篇文章。
注意,以下的步驟不適合對 FreeBSD 不熟的人使用。同時,我們也不保證以下的步驟能夠達成你想要的目的,如果您使用以下步驟而造成任何問題,我們不負任何責任。
- 開兩個 login shell,都先 su 成 root,也就是說下面的指令不要透過 sudo 處理,原因後述。
- 先把
/usr/src
下的東西更新到RELENG_5_4
,可以透過 net/csup 或是 net/cvsup-without-gui 更新。 - 修改
/etc/rc.conf
,將background_fsck="NO"
加上去以避免不穩定的 background fsck 造成系統出問題。 - 看
/etc/make.conf
的設定,主要是要把CPUTYPE=some_kind_of_cpu
改成CPUTYPE?=some_kind_of_cpu
,以及把CFLAGS
、CXXFLAGS
與COPTFLAGS
拿掉,改用系統預設值。 - 更新完以後執行
make buildworld
,此時另外一個窗可以開始改 kernel config file,建議整個重寫會比較安全。(如果你認為你對 FreeBSD 有經驗的話,可以用 vimdiff 同步改) - 當
buildworld
完以後開始make buildkernel
。 - 當
buildworld
與buildkernel
都成功後,將/sys/i386/conf/GENERIC.hints
複製一份到/boot/device.hints
:
cp /sys/i386/conf/GENERIC.hints /boot/device.hints
- 接下來到
/usr/src/sys/boot
下執行make STRIP="" install
更新 boot loader。 - 然後跑
make installkernel
,此時會建立/etc/pam.d
這個目錄,這會使得 sshd 無法登入,這也就是先前要求你先登入且先變成 root 的原因。 - 下面的步驟在
UPDATING
裡要求你要在 single user mode 做,這時候就要想辦法解決: - 先到其他台 (5.x 或 6.x 的機器) 執行
dd if=/dev/random of=blah count=1 bs=4k
,然後將產生出來的blah
(應該是 4096 bytes) 複製到要升級機器上的/entropy
。 - 用
mergemaster -p
同步/etc/master.passwd
與/etc/group
(主要是補上幾個 user 與 group)。不過有些人可能會mergemaster
的 merge 功能覺得太簡陋,如果你對 vimdiff 熟悉,可以用vimdiff /etc/master.passwd /usr/src/etc/master.passwd
同步,再用mergemaster -p
更新其他的部分。記得,做完後要進入vipw
再強制寫入,讓系統將master.passwd
的內容同步到/etc/pwd.db
與/etc/spwd.db
。而/etc/group
的部分改完就會生效,不需要用程式處理。 - 執行
rm -rf /usr/include/g++
。 - 使用
mergemaster -i
更新系統檔案。(主要是/etc
下的 scripts) - 接著,最後的
installworld
仍然要在 single user mode 下執行,所以我們要修改/etc/rc
的開頭,使得重新開機後在 single user mode 下執行installworld
,然後重新開機:
if [ -r /not.ok ]; then /sbin/mount -u / /sbin/mount -a /bin/rm -f /not.ok cd /usr/src /usr/bin/make installworld DESTDIR=/ cd / /sbin/umount -a /sbin/reboot fi
然後把
/not.ok
生出來:touch /not.ok
接著重開機等個十到二十分鐘 (看機器的速度),祈禱他成功 :p
升級完畢以後,記得把 /etc/pam.conf
砍掉。
另外,雖然有 compatible library 可以用,但還是要找個時間把系統的 packages 重新安裝,這點可以透過 portupgrade 幫你處理,不過有一些 packages 已經放在 base system 了,在 portupgrade 升級完畢後應該就不會有 dependency,可以直接移掉:
devel/libgnugetopt
devel/readline
net/portsnap
sysutils/rc_subr
DK大神武英明阿阿阿!
照上面的步驟,要把 entropy 弄過去的時候,會不能 login,建議先弄再 installkernel。
另外,在 mergemaster -i 那次之後,ssh 應該就又可以動了。
mergemaster -p 我覺得用 vimdiff 比較好弄。
建議在 make installkernel 之後把 /etc/pam.d 砍掉,
mergemaster -i 跑到一半的時候會把 pam.d 建起來,
pam.d裡面的檔案也都會建立,這樣就可以用 ssh 登入以及 su 了
不然mergemaster -i到一半的時候斷線,那就要跑到主機前面更新 XD
5.4 -> 6.1 可以直接 build, 不用先從別台挖東西過來 ;p 5.4 -> 6.2 我每次好像都會 build 失敗 XD