HOWTO:The Linux Bootdisk

作者: Tom Fawcett ( [email protected])

譯者: 朱漢農

v4.0, April 2000, 翻譯日期: 27 July 2000


本文描述如何設計與建造你自己的 Linux boot/root 磁片。這些磁片能用來當做救援磁片 (rescue disks) ,或是能用來測試新系統元件 (components) 。在企圖建造你自己的 bootdisk 之前,你應該要相當熟悉系統管理工作。如果你只是想要一張緊急時使用的救援磁片,請參考 Pre-made bootdisks 。 目錄


1. 前言

這份文件可能已經過期了。 如果標題頁上的日期距今已超過 6 個月,那麼請查閱 Bootdisk-HOWTO homepage 看看是否已有較新的版本。

雖然本文以 text 格式也是可以閱讀,但是因為印刷符號的關係, 最好 還是以 Postscript (.ps) 、 PDF 或 HTML 的格式來閱讀。

1.1. 版本注意事項

Graham Chapman 是原本 Bootdisk-HOWTO 的作者,他一直提供支援到 version 3.1 。 Tom Fawcett 大約是在 kernel v2 問市時成為合作作者。他是本文目前的維護者。

文中資訊是給在 Intel 平台上運作的 Linux 使用。其中許多資訊也許能應用在其它平台的 Linux ,但是我們並沒有嘗試在其它平台製作 bootdisk ,也沒有相關的資訊。如果你有在其它平台上製作 bootdisk 的經驗,請與我們聯絡。

1.2. 尚未完成的事

有任何自願者嗎 ?

  1. 請描述 (或是鏈結到另一份有敘述的文件)如何製作其它可開機的類磁片物品,諸如 CDROMs, ZIP disks 與 LS110 disks 。
  2. 請描述如何處理巨大的 libc.so 共享函式庫。基本上可選擇獲取較舊、較小的函式庫,或是刪減現有的函式庫。
  3. 重新分析 distribution bootdisks 與更新 "How the Pros do it" 這一節。
  4. 刪減敘述關於如何升級現有 distribution bootdisks 的章節。 This is usually more trouble than it's worth.
  5. 重寫 / 潤飾 Troubleshooting 這一節。

1.3. 回應與感謝

我接受任何關於本文內容之回應,無論是好是壞。我/我們 已力求這份文件內的指令與資訊是正確而可靠的。如果你發現任何錯誤或遺漏,請讓我知道。在撰寫時, 請指出你所參考的文件之版本號碼 。

我們感謝許多協助修正與給予建議之人。他們的貢獻使得本文比我們自己獨立完成它時還來得更好。

請各位利用上述的 email 地址,給予作者你的批評、指正與疑問。我不介意嘗試回答任何問題,但是如果你有特定問題是關於你的 bootdisk 不能運作,那麼請先閱讀 Troubleshooting

1.4. 散佈政策

Copyright (c) 1995,1996,1997,1998,1999,2000 by Tom Fawcett and Graham Chapman. 本文可以在 Linux Documentation Project License 的條件下流通。如果你未能拿到此 license ,請與作者聯絡。

本文是一份免費文件。我們發行它是希望它能有助於你,但是 不能給你任何保證 ;本文也沒有 具有商業能力 或 適合特定用途 的保證。

2. 簡介

Linux 開機磁片 (boot disks) 在很多情況下是很有用的,諸如

有好幾種獲得 boot disks 的方法:

有些人選擇最後一種方法,如此他們能靠自己動手做。這樣子,如果某處發生問題,就能找出辦法去解決問題。此外也可以學到很多有關 Linux 如何運作的知識。

本文假設讀者已熟悉基本的 Linux 系統管理觀念。舉例來說,你應該知道有關目錄、 filesystems 與軟碟片的議題。你也應該知道如何使用 mount 與 df 。你還應該知道 /etc/passwd 與 fstab 這兩個檔案的用途以及它們看起來像什麼。最後,你應該知道 HOWTO 文件內大部分的指令,都要以 root 的身份來執行。

剛開始製作你自己的 bootdisk 是很複雜的。如果你未曾讀過 Linux FAQ 與相關文件,諸如 Linux Installation HOWTO 與 Linux Installation Guide ,那麼你不應該嘗試建造開機磁片。如果你只需要緊急時用的 bootdisk ,下載一個別人事先完成的 bootdisk 拿來用會 更 為容易。請參考下面的 Pre-made bootdisks 以得知在哪裡可以找到這些東西。

3. Bootdisks與開機流程

bootdisk 基本上是放在軟碟片內的一個小型而自足的 Linux 系統。它必須執行許多和完整又 full-size 的 Linux 系統相同的功能。在建造 bootdisk 之前,你應該了解基本的 Linux 開機流程。我們在此只做基本的介紹,但已足夠讓你了解本文之後的內容。很多細節與替代選項已被省略。

== 開機流程 ===

所有 PC 系統開始開機流程都是藉由執行 ROM (明確地說,就是 BIOS) 中的程式,從開機磁碟機的第 0 磁區、第 0 磁柱載入可供開機的磁區。開機磁碟機通常是第一台軟碟機 (如 DOS 的 A槽 與 Linux 的 /dev/fd0)。接著 BIOS 會嘗試執行這個磁區。在大部分可開機的 disks 上,第 0 磁區、第 0 磁柱包含以下兩者之一:

如果一個 Linux kernel 已利用 raw-copied 的方式置入一張磁片內,那麼這張磁片的第一個磁區就是 Linux kernel 本身的第一個磁區。這個磁區將從開機設備載入 kernel 的剩餘部分以繼續開機流程。

一旦 kernel 載入完畢,一些基本設備也完成初始化 (initialization) 。然後系統將嘗試從某個設備載入以及掛上 (mount) root filesystem 。所謂的 root filesystem 只是一個被掛上當作 "/" 目錄的 filesystem 。 kernel 必須被告知可從哪裡找到此 root filesystem ;如果 kernel 在那裡找不到一個可載入的影像檔 (image) ,系統就會停止運作 (halt) 。

在某些開機情況下 -- 常常是從軟碟片開機 -- root filesystem 會被載入到 ramdisk 中,也就是被系統所存取的 RAM ,如同系統存取磁碟一般。為何系統會載入到 ramdisk 的理由有二。第一, RAM 是幾個比軟碟片快的有序磁性體,所以系統在其上運作較快; 第二, kernel 可以從軟碟片載入一個 壓縮的filesystem 並且在解壓縮後放到 ramdisk 上,如此可讓更多的檔案儲存在軟碟片上。

一旦 root filesystem 被載入並掛上,你會看到一行訊息像:

此時系統會在 root filesystem 上找到 init 程式 ( 在 /bin or /sbin) 並執行它。 init 讀取它的組態設定檔 (configuration file) /etc/inittab ,找出檔中標明 sysinit 的一行,並執行被指名的script。這個 sysinit script 通常類似 /etc/rc 或 /etc/init.d/boot 這兩個檔。這個 script 是一組建立基本系統服務的 shell 指令,諸如:

這個 script 常會啟動其它各種不同的 scripts 執行模組的 (modular) 初始化。舉例來說,在一般的 SysVinit 架構下, /etc/rc.d/ 這個目錄包含一個複雜的子目錄架構,其中的檔案指出如何啟動與關閉大部分的系統服務。然而,在一張 bootdisk 上,這樣的 sysinit script 常常是非常簡單的。

當 sysinit script 結束後,控制權回到 init 上,接著進入 預設的runlevel ,此預設的 runlevel 以 initdefault 這個關鍵字被指定在 inittab 內。此 runlevel line 通常指定一個像 getty 的程式,這個程式負責處理 console 與 ttys 之間的通訊。事實上,就是 getty 程式在螢幕上印出熟悉的 "login:" 提示。 getty 程式並轉而呼叫 login 程式以處理 login 是否有效,並於之後建立 user sessions 。

3.1. 磁碟類型

如果你已了解基本的開機流程,那麼我們現在可以定義所涉及到之各種不同類型的磁碟。我們將磁碟分類成四種。本文與在此討論所稱之 "磁碟 (disk)" 除非有特別聲明,否則都是指軟碟片,雖然絕大部分的討論也同樣可應用在硬碟上。

一般而言,當我們提及 "建造一張 bootdisk" 時,是指造出 boot ( kernel ) 與 root (files) 這兩個部分。這兩個部分不是放在一起 (一張單張的boot/root disk) ,就是兩張分開的磁片 (boot + root disks) 。對救援磁片而言最具彈性之做法,可能是使用兩張分開的 boot 與 root 磁片,再加上一張或多張的 utility diskettes 以處理多出來的東西。

4. 建立一個root filesystem

造出 root filesystem 涉及選擇能讓系統正常運作所必備的檔案。在這一節中,我們將敘述如何建造一個 壓縮的 root filesystem 。在磁片上建造一個直接掛上做為根目錄 (root) 之未經壓縮的 filesystem 是較不普遍的觀念;這個替代方案敘述在 Non-ramdisk Root Filesystem 這一節中。

4.1. 概觀

root filesystem 必須包含支援完整 Linux 系統運作所需的每一個項目。為了能夠達成這個目的,這張磁片必須包括能讓 Linux 系統運作最起碼 (minimum) 的需求:

當然,任何系統只有在你能於其上執行某些東西時才會顯得有用,而一張 root 磁片通常只有在你能做到以下事情時才會顯得有用:

我們將敘述如何建造一個 壓縮的 filesystem ,就是平時被壓縮在磁片上,只有當開機時,才會解壓縮後存入ramdisk 。 用壓縮 filesystem 的方式,你可以在一張標準的 1440K 磁片上放入很多檔案 (大約 6 megabytes) 。因為 filesystem 比磁片大很多,我們不能直接把它建在磁片上。我們必須在其它地方建立它,壓縮它,然後再把它 copy 到磁片上。

4.2. 製作 filesystem

為了建造如此的一個 filesystem ,你需要一個多出而夠大的設備,能夠讓你在壓縮之前存放所有的檔案。你將需要一個能夠存放大約 4 megabytes檔案的設備。有以下幾種選擇:

在你選擇其中一種方法後,請準備 DEVICE 以:

這行指令送出一堆 0 把DEVICE填滿。用 0 填滿 device 是關鍵的一步,因為 filesystem之後將會被壓縮,所以所有未使用的部分應被用 0 填滿以達到最大的壓縮比。無論何時你從你的 root filesystem 刪除檔案,請記得這個事實。實際上 filesystem 只是釋出 (de-allocate) 這些 blocks , 但是並沒有再把它們填為 0 。如果你執行過很多次刪除與 copy 的動作,你的壓縮 filesystem 最後會比必要的大出很多。

下一步就是造出 filesystem 。 Linux kernel 承認兩種能讓 root disks 自動地被 copy 到 ramdisk 上的 file system 。它們是 minix 與 ext2 ,其中 ext2 是比較受歡迎的。如果使用 ext2 ,你會發現使用 -i 選項指定比預設值更多的 inodes 是有助益的;我們建議用 -i 2000 ,這樣你就不會用完 inodes 。如果不用上述選項,你可以移除許多不必要的 /dev 檔案以節省 inodes 。 mke2fs 預設會造出 360 個 inodes在一張 1.44Mb 的磁片上。我發現在我目前的救援 root 磁片上, 120 個 inodes 是相當足夠了,但是如果你把所有的設備檔都放入 /dev 目錄中,那麼你很容易會超過 360 個inodes 。使用壓縮的 root filesystem 可讓你擁有較大的 filesystem ,同時預設會有更多的 inodes ,但是你仍然必須要不就是減少檔案數量,要不就是增加 inodes 數目。

因此,你所使用的指令看起來會像這樣:

(如果你使用的是一個 loopback device ,那麼請用你目前所用的磁碟檔案替換掉上面的 DEVICE 。)

mke2fs 指令會自動地偵測可獲得的空間,然後依據偵測對自身進行組態設定。 -m 0 參數避免保留空間給 root ,因此可提供更多可用的磁碟空間。

下一步,掛上這個 device :

(如果 mount point 並不存在,你必須自行造出一個 mount point /mnt 。) 在剩下的章節中,所有的目的 (destination) 目錄都被假設是相對於 /mnt 。

4.3. 移植檔案系統

以下是你的 root filesystem 最起碼該有的目錄

此處所呈現之目錄架構僅供 root diskette 使用。真正的 Linux 系統有一套更為複雜且設計良好的架構方法,稱為 Filesystem Hierarchy Standard ,它決定檔案應該如何放置。 :

上述目錄的其中三個在 root filesystem 上會是空的,所以它們只需要用 mkdir 造出來。 /proc 目錄基本上是一個把 proc filesystem 放置於其下的 stub 。 /mnt 與 /usr 這兩個目錄只是在 boot/root 系統運作時所使用的 mount points 。因此再重覆一次,這些目錄只需要被造出來就可以了。

剩下的四個目錄描述於以下各節。

4.4. 對 PAM 與 NSS 的提供

你的系統可能會需要動態地載入未被 ldd 所見的函式庫。如果你沒有提供函式庫給這些項目,那麼你會在登錄 (log in) 或使用你的 bootdisk 時遭遇到困難。

4.5. 模組

如果你有一個模組化的 kernel ,你必須考量在開機後,你想要從你的 bootdisk 上載入哪一種模組。你可能會想要包括 ftape 與 zftape 模組 (如果你的備份磁帶是floppy tape),以及給 SCSI 設備用的模組 (如果你有 SCSI 設備),也可能是 PPP 或 SLIP 支援的模組 (如果你在緊急情況下想要存取網路)。

這些模組可能會被放在 /lib/modules 。你同時也應該包括 insmod, rmmod 與 lsmod 。根據你是否想要自動地載入模組,你可能也要包括 modprobe, depmod 與 swapout 。如果你使用 kerneld,請與 /etc/conf.modules 一起包括進來。

然而,使用模組的主要優點在於你可以把非關鍵 (non-critical)模組移到 utility disk 上,在需要用到時才載入,這樣在你的 root disk 上會使用比較少的空間。如果你要處理許多不同的設備,這個方法比建立一個內建支援許多設備的巨大 kernel 來得好。

請注意,為了啟動 (boot) 一個壓縮的 ext2 filesystem ,你必須有 ramdisk 與內建 ext2 支援。 它們不能夠以模組的方式被提供。

4.6. 一些最後的細節

某些系統程式,諸如 login ,當 /var/run/utmp 檔與 /var/log 目錄不存在時,會發出警告。所以:

最後,在你設定 (set up) 完所有你所需的函式庫後,執行 ldconfig 以在 root filesystem上重新製作 (remake) /etc/ld.so.cache 。這個 cache 會告訴 loader 到哪裡找到函式庫。要重新製作 ld.so.cache,請下達以下指令:

chroot 是必要的,因為 ldconfig 總是會為 root filesystem 重新製作 cache 。

4.7. Wrapping it up

一旦你完成 root filesystem 的建構工作,就 unmount 它,將之 copy 成一個檔案並壓縮它:

結束後,你會有一個名為 rootfs.gz 的檔案,這就是你被壓縮過的 root filesystem。你應該檢查它的 size 以確保它能放在一張軟碟片上;如果不行,你就必須回溯並移除一些檔案。 Reducing root filesystem size 這節有一些提示,告訴你有關減少 root filesystem 的 size 。

5. 選擇一個 kernel

現在,你已有一個完整的被壓縮過的root filesystem。下一步是要建立或是選擇一個 kernel 。在大部分的情況下, copy 你目前所使用的 kernel 並且從它啟動軟碟片是可能的。然而,會有一些情況,你會希望建立一個獨立的 (separate) kernel 。

理由之一是 size 的考量。如果你正建立一張單一的 boot/root 磁片, kernel 將會是磁片上最大的檔案之一,也因此你必須盡可能地減少 kernel 的 size 。為了減少 kernel size ,請用能支援所想要的系統之必要最起碼的設備來建立 kernel 。這是指丟去你所不想要的每一項。網路功能是可以丟去的好選擇,另外還有當運作你的 boot/root filesystem 時,任何你所不需要的磁碟機與其它設備的支援。如同前述,你的 kernel 必須有 ramdisk 與 ext2 支援內建於其中。

如果你已完成一套最起碼的 (minimum) 設備組合以便於將之放入 kernel 中,那麼接下來你需要開始進行要把什麼加入回來。或許一套 boot/root 磁片組之最常見用途,是為了要能檢查與回復 (restore) 一個已損毀的 root file system ,而為了達成這個目標,你需要 kernel 的支援。舉例來說,如果你的備份都放在磁帶上,並使用 Ftape 存取你的磁帶機,那麼,如果你失去了你目前的root drive與含有 Ftape 的 drive ,你將不能夠從你的備份磁帶進行回復儲存。你將必須重新安裝 Linux ,下載並重裝 ftape ,然後試著讀取你的備份。

此處的要點是,無論你已加入什麼 I/O 支援到你的 kernel 內以支援備份,你同時也應該把它們加入到你的 boot/root kernel 中。

實際建造 kernel 的程序詳述在隨附於 kernel 的文件中。你可以輕易地照著指示進行,所以可以 /usr/src/linux 為起點。如果你在建造 kernel 上有困難,你或許不應該企圖不擇手段地建造 boot/root systems 。請記得用 make zImage 壓縮 kernel 。

6. 把它們放在一起:製作磁片(組)

進行到這裡,你已經有一個 kernel 與一個壓縮的 root filesystem 。如果你正在製作一張 boot/root 磁片,請檢查它們的 size ,以確定它們都能放在同一張磁片上。如果你正在製作一套兩張磁片的 boot + root 磁片組。請檢查 root filesystem 以確定它能放在一張磁片上。

你應該決定是否使用 LILO 以啟動 bootdisk的 kernel 。替代的方法是直接把 kernel copy 到磁片上,然後不使用 LILO 開機。使用 LILO 的好處在於讓你能夠提供一些參數給 kernel ,這些參數對初始化硬體來說可能是必要的(請檢查你系統上的 /etc/lilo.conf 檔。如果這個檔存在,而且有一行像append=...,你可能需要這個特點 (feature))。使用 LILO 的缺點在於建造 bootdisk 變得更為複雜,並且佔用稍嫌較多的空間。你將必須設定一個小型而獨立的 filesystem ,我們稱之為 kernel filesystem,在其中你傳送 kernel 以及一些 LILO 所需的其它檔案。

如果你將要使用 LILO ,請繼續讀下去;如果你要直接傳送 kernel ,先跳過此,直接到 Without using LILO 這一節。

6.1. 用 LILO 傳送 kernel

你所必須做的第一件事是為 LILO 編寫一個小型的組態檔。這個檔看起來像這樣:

關於這些參數的說明請看 LILO's user documentation 。你或許也會想從你硬碟上的 /etc/lilo.conf 檔,加入一行 append=... 到這個組態檔中。

把這個組態檔存成 bdlilo.conf 。

現在你必須製作一個小型的檔案系統,我們稱之為 kernel filesystem ,有別於 root filesystem 。

首先,指出這個 filesystem 應該會有多大。用 blocks 計算你 kernel 的 size (這個 size 用 ls -l KERNEL 顯示出來,是被 1024 所除並強迫進位),然後加 50 。這個 50 blocks 是估計的空間,為 inodes 與其它檔案所需。如果你想要,你可以精確地計算這個數字,或是就用 50 就好了。如果你正在製作兩張磁片的磁片組,你會高估這個空間,因為無論如何第一張磁片只給 kernel 使用。我們稱這個數字會 KERNEL_BLOCKS 。

請把軟碟片放入軟碟機 (為求簡便,我們假設是 /dev/fd0),然後在其上製作 ext2 kernel filesystem 。

-i 8192 指定我們想要每 8192 bytes 一個 node 。接下來, mount 這個 filesystem ,移除 lost+found 目錄,然後為 LILO 造出 dev 與 boot 這兩個目錄:

再來,造出設備檔 /dev/null 與 /dev/fd0 。不用尋找設備號碼,你只要從你的硬碟上用 -R copy它們:

LILO 需要一份它的 boot loader 的 copy , boot.b ,你可以從你的硬碟得到它。它通常是放在 /boot 目錄內。

最後,隨附你的 kernel , copy 你在上一節所編寫的 LILO 組態檔。它們兩者可以被放在根目錄下。

LILO 所需的每一項現在都在 kernel filesystem上,所以你已準備好去執行它。 LILO 的 -r 旗號(flag)被用作安裝 boot loader 在某個其它的 root 上:

LILO 應該可以在無錯的情況下執行,在此之後,你可以看看你的 kernel filesystem ,應該長得像這樣:

如果檔案 size 和你自己的 filesystem 有稍微不同,請不用擔心。

現在請把磁片留在軟碟機內,然後前進到 Setting the ramdisk word 這一節。

6.2. 不使用 LILO 來傳送 kernel

如果你 不 使用LILO,那麼就用 dd 指令來傳送 kernel 給 bootdisk :

在這個例子中, dd 寫入了 353 個完整記錄(records) + 1個partial record ,所以 kernel 佔用了 354 個軟碟片的 blocks 。這個數字稱為 KERNEL_BLOCKS ,請記得它,這個數字要給下一節使用。

最後,請設定 root device 為軟碟片自己,然後再設定 root 要被載入成 read/write :

在第二個 rdev 指令中,請小心地使用 -R 。

6.3. 設定ramdisk

在 kernel image內的是 ramdisk word ,它伴隨其它選項,指定了 root filesystem 應該在哪裡被找到。這個 word 會被以 rdev 指令,來進行存取與設定,而它的內容被解釋如下:

如果 bit 15 被設定,在開機時 (boot-up) ,會提示你把一張新的軟碟片放入軟碟機中。這對一套雙磁片的開機磁片組來說是必要的。

依據你是建造一張單一的 boot/root 磁片,還是兩張 "boot + root" 的磁片組,這裡會產生兩種情況。

  1. 如果你是建造一張單一磁片,壓縮的 root filesystem 會被放置在 kernel 之後,所以 offset 會是第一塊 free block (這個值應該會與 KERNEL_BLOCKS 相等) 。 Bit 14 會被設定為 1 ,而 bit 15 會被設定為 0 。舉例來說,假設你正建造一張單一磁片,而 root filesystem 將自 block 253 (10進位)開始。那麼, ramdisk word 值應該是 253 (10進位) , bit 14 設為 1 而 bit 15 設為 0 。要計算這個值,你可以簡單地加一加這個 10 進位數字。 253 + (2^14) = 253 + 16384 = 16637 。如果你並不十分了解這個數字從何而來,把這數字放到工程計算機上,然後把它轉換為 2 進位,
  2. 如果你建造的是一套雙磁片組,那麼 root filesystem 將自第二張磁片的 block 0 開始,所以 offset 為 0 。 Bit 14 設為 1 而 bit 15 設為 1 。在這個情況下, 10 進位值是 214 + 215 = 49152 。

在仔細地為 ramdisk word 計算後,請用 rdev -r 設定它。請注意要使用 10 進位 值。如果你使用 LILO ,傳給 rdev 的引數在此應該是 mounted kernel path ,比如說 /mnt/vmlinuz;如果你用 dd 來 copy kernel ,替換成使用軟碟機名稱( 比如說 /dev/fd0)。

如果你使用 LILO ,現在請把磁片 unmount 。

6.4. 傳送root filesystem

最後一步是要傳送 root filesystem 。

恭喜你,已經完成了!

在把 bootdisk 挪為緊急使用之前,請記得先測試它 !如果你的成品不能執行,請繼續讀下去。

7. 問題解決

當建造 bootdisks 時,開始的幾次嘗試結果常常是無法開機。建造一張 root disk 的一般方法是組合來自你現有系統的元件 (compnents) ,接著嘗試與得到這個以磁片為基礎的系統 (diskette-based system) ,直到它在 console 上顯示訊息。一旦它開始與你交談,這場戰鬥就結束一半了,因為你可以了解它在抱怨什麼,而且你可以解決個別的問題直至系統能平順地運作。如果系統停止運作而沒有任何說明,要找到這原因會是一件困難的事。為了讓系統能啟動到能與你交談的階段,這需要使用到好幾種元件,而且這些元件要經過正確地組態。以下是調查系統無法與你交談之問題的建議程序:

以上已經涵蓋一般部分,以下是一些更特定的檔案與檢查項目:

  1. 請確定 init 是以 /sbin/init 或 /bin/init 的形式被包括進來。並且確認它是可執行的。
  2. 請執行 ldd init 以檢查 init 的函式庫。通常這個就是 libc.so ,但是請無論如何還是檢查一下。請確定你已放入了必備的函式庫與 loaders。
  3. 請確定你把正確的 loader 給你的函式庫 -- ld.so 是給 a.out 而 ld-linux.so 是給 ELF 。
  4. 請針對 getty (或某種類似 getty 的程式,諸如 agetty, mgetty 或 getty_ps) 的呼叫,檢查你bootdisk filesystem上的 /etc/inittab。請針對你硬碟的 inittab 檢查兩次。再檢查你所使用的程式的 man pages 以確定這些是有意義的。 inittab 可能是最詭異的部分,因為它的語法與內容,依據所使用的 init 程式與系統本質而有所不同。解決的唯一之道就是去閱讀 init 與 inittab 的man pages,然後再正確地做出既存系統開機時所做的事。請檢查以確定 /etc/inittab 有一個系統初始化的記錄 (entry) 。它應該包括一個指令以執行必定存在的系統初始化 script 。
  5. 如同 init ,對你的 getty 執行 ldd 以了解它需要什麼,同時確定必備的函式庫檔案與 loaders 是否被放入你的 root filesystem 。
  6. 請確認你已放入一個 shell 程式 (e.g., bash or ash),它能夠執行你所有的 rc scripts 。
  7. 如果在你的救援磁片上,有一個 /etc/ld.so.cache 的檔案,請重新製作 (remake) 它。

如果 init 啟動,但是你卻得到一行訊息像是:

它是來自於 init ,通常指出 getty 或 login 被終結只要 init 啟動。請檢查 getty 與 login 的可執行檔與相依的函式庫。請確定在 /etc/inittab 內的呼叫 (invocations) 是正確的。如果你得到來自 getty 的奇怪訊息,它可能是指 /etc/inittab 內的呼叫格式是錯誤的。

如果你得到一個 login 提示 (prompt) ,然後你輸入一個有效的 login name ,但是系統卻立即提示你要輸入另一個 login name ,那麼這個問題可能是出在 PAM 或 NSS 。請看 PAM and NSS 這一節。問題也可能是你使用 shadow passwords 而你卻沒有 copy /etc/shadow 到你的 bootdisk 上。

如果你嘗試去執行某個可執行檔,諸如 df ,而這個執行檔是在你的救援磁片上,執行時卻出現像這樣的訊息: df: not found ,這時請檢查兩件事:(1)請確定包含二進位檔的目錄有設定在你的 PATH ,(2)請確定你有程式所需的函式庫 (與 loaders)。

8. 其它各種主題

8.1. 減少 root filesystem 的 size

有時 root filesystem 會因太大而無法塞入一張軟碟片內,甚至在壓縮過後還是這樣。這裡有一些方法可減少 filesystem 的 size :

  1. 增加磁碟片密度 (density) 。依照預設,軟碟片會以 1440 K 來進行格式化,但是現在也有更高密度的格式。 fdformat會為以下 sizes 的磁片進行格式化: 1600, 1680, 1722, 1743, 1760, 1840, 以及 1920 。大部分的 1440 K 軟碟機可支援 1722 K ,我一直都是使用這個來製作 bootdisks 。請參考 fdformat man page與 /usr/src/linux/Documentation/devices.txt 。
  2. 替換你的 shell 。一些在 Linux 上廣受歡迎的 shells ,諸如 bash 與 tcsh ,是相當大且需要許多函式庫。 Light-weight 的選擇於是存在,諸如 ash, lsh, kiss 與 smash,它們小很多而且只需要很少 (或是不需要)函式庫。大部分這些用來代替的 shells 可以在 http://metalab.unc.edu/pub/Linux/system/shells/ 找得到。請確定你所使用的任何 shell ,能夠執行你放在你 bootdisk 內的所有 rc 檔案中的指令。

  3. 刪去函式庫與二進位檔 。很多函式庫與二進位檔一般而言是未被刪去的 (包括debugging symbols)。如果如此,對這些檔案執行 file 會告訴你 not stripped 。 當 copy 二進位檔到你的 root filesystem 時,這是一個好練習去使用:

    •       objcopy --strip-all FROM TO
         
    當 copy 函式庫時,請確定使用的是 strip-debug 而不是 strip-all 。
  4. 如果你在製作 root filesystem 時,刪除或移動過多檔案,請再重新製作一次。請看上述關於不要在 filesystem 內有 dirty blocks 之重要性的注意事項。
  5. 移動非關鍵檔案到工具磁片 (utility disk) 上 。如果你的一些二進位檔對 boot 或 login 來說並非立即需要,那麼你就可以把它們移到工具磁片上。細節請看 Building a utility disk 這一節。你同樣可考慮把 modules 移到工具磁片上。

8.2. Non-ramdisk root filesystems

Building a root filesystem 這一節曾給予指示以建造一個壓縮的 root filesystem ,它會在系統開機時被載入到 ramdisk 。這個方法有許多優點,所以通常都採用此法。然而,一些只有一點點記憶體的系統無法負擔此法所需的 RAM ,因此,這些系統必須使用直接從軟碟片掛上的 root filesystems 。

這樣的 filesystems 實際上比壓縮的 root filesystems 更容易建造,因為它們可以被造在一張磁片上,而非某個其它的設備上,另外,它們也不必被壓縮。當異於前述的指示時,我們將敘述該程序的要點。如果你選擇這樣做,請記得你可獲得的剩餘 空間會變少 。

  1. 請計算你將有多少空間可供 root files 使用。 如果你建造的是一張單一的 boot/root 磁片,你必須讓所有給 kernel 的 blocks 以及所有給 root filesystem 的 blocks 都能容納於同一張磁片上。
  2. 使用 mke2fs ,在適當 size 的軟碟片上造出一個 root filesystem 。
  3. 如同前述的方法殖入於此 filesystem 。
  4. 完成後, unmount 此 filesystem 並且傳送它使之成為一個磁片檔案,但是 不要壓縮它 。
  5. 以前述之方法,把 kernel 傳送到一張軟碟片上。當計算 ramdisk word 時, 把 bit 14 設成 0 ,以指示不要把 root filesystem 載入到 ramdisk 。請以前述之方法執行 rdev 指令。
  6. 如同以往,傳送此 root filesystem 。

有好幾種捷徑你可採用。如果你建造的是一套雙磁片組,你可以直接把完整的 root filesystem建造在第二張磁片上,而且你並不需要把它傳送成一個硬碟檔案然後再存回磁片上。同樣地,如果你建造的是一張單一的 boot/root 磁片而且使用 LILO ,你可以在整張磁片上建立 單一的 filesystem,包含 kernel 、 LILO files 與 root files ,然後只要執行 LILO 做為最後一步。

8.3. 建造一張工具磁片

建造一張工具磁片相對來說簡單多了 -- 只要在一張已格式化的磁片上造出一個 filesystem ,然後 copy 檔案於其上即可。為了跟 bootdisk 一起使用它,請在系統啟動以後,用手動的方式 mount 它。

在前面的指示中,我們曾提及 utility disk 可以被 mount 做為 /usr 。在這個情況下,二進位檔可以被放在你 utility disk 之 /bin 目錄內,以便於將 /usr/bin 設入你的 path 中可以存取它們。二進位檔所需之其它函式庫被放在 utility disk 之 /lib 目錄內。

當設計 utilitu disk 時,有幾個重點要記住:

  1. 不要把關鍵的系統二進位檔或函式庫放到 utility disk 上,因為直到系統順利啟動之前, utility disk 不會被掛上,其上的檔案也無法供系統使用。
  2. 你不能同時存取一張軟碟片與一台磁帶機。意指如果你有一台磁帶機,那麼當你正在使用 (mount) utility disk 時,你將不能存取那台磁帶機。
  3. 存取 utility disk 上的檔案會很慢。

Sample utility disk directory listing 提供了utility disk的檔案之樣本。以下是一些建議關於一些你會發現有用的檔案:檢查與操作磁片(format, fdisk)、 filesystems (mke2fs, fsck, debugfs, isofs.o)的程式,小型的文書編輯器 (elvis, jove),壓縮與檔案工具 (gzip, tar, cpio, afio), 磁帶工具 (mt, tob, taper),通訊工具 (ppp.o, slip.o, minicom)與給設備使用的工具 (setserial, mknod)。

9. How the pros do it

您可能已經注意到,那些被諸如 Slackware、RedHat、Debian 等主要 distribution 所使用的 bootdisks ,似乎比本文中所描述的還要來得複雜許多。專業的 distribution bootdisks 以在此所提出的相同原則為基礎,但是採用各式各樣的技巧,因為它們的 bootdisks 有一些額外的需求。第一,它們必須能夠在各種不同的硬體上運作,所以它們必須能夠與使用者互動,並且能載入各式各樣的設備驅動程式。第二,它們必須準備以許多不同的安裝選項、不同的自動化程度來運作。最後, distribution bootdisks 通常結合了安裝磁片與救援磁片的能力。

某些 bootdisks 使用名為 initrd(initial ramdisk)的特性。這個特性大約在 2.0.x 版時引入,它允許 kernel 以兩階段開機。當 kernel 開機時,它從 boot disk 載入一個initial ramdisk映像檔。這個 initial ramdisk 是一個 root filesystem ,包含一個在真正的 root fs 被載入之前所執行的程式。這個程式通常會檢查作業環境, 以及/或 要求使用者選擇不同的開機選項,例如選擇從哪一個設備載入真正的 rootdisk 。一般來說,它會載入未被內建在 kernel 內的額外模組。當這個初始化 (initial) 程式結束 (exit) 時, kernel 就載入真正的 root 映像檔,開機動作將依一般情況繼續執行下去。若要進一步得知 initrd 的資訊,請詳閱你機器上的 /usr/src/linux/Documentation/initrd.txt 。

以下是每一家 distribution的安裝磁片如何運作的摘要,這份摘要以檢閱 (inspect) 它們的filesystems 以及/或 它們的原始碼為基礎。我們不保證這份資訊完全正確無誤,或是自從版本noted以來,這些運作方式未被改變。

Slackware(v.3.1) 使用一種與 Transferring the kernel with LILO 這節所描述類似的前向式 (straightforward) LILO 開機法。 Slackware 的 bookdisk 利用 LILO 的 訊息 參數印出一個 bootup 訊息 (“Welcome to the Slackware Linux boot kernel disk!”) 。假如必要的話,這裡會指示使用者輸入一個開機參數行(boot parameter line)。在開機之後,一個root檔案系統會從第二張磁片載入。此時使用者喚起(invoke)一個 setup script,這個script將啟動安裝程序。Slackware並非使用一個模組化 kernel ,相反地,它提供許多不同的 kernel ,並且靠使用者自己選擇一個符合 他/她 硬體需求的 kernel 。

RedHat(v.4.0) 也使用 LILO 開機法。它從第一張磁片載入一個壓縮的 ramdisk ,這動作執行一個 custom init 程式。這個程式查詢驅動程式,然後,假如必要的話,從 supplemental 磁片載入額外的檔案。

Debian(v1.3) 可能是最複雜的安裝磁片集。它使用 SYSLINUX loader 去安排各式各樣的載入選項,然後使用一個 initrd 映像檔指示使用者完成安裝程序。它顯然使用了一個客製化的 init 與一個客製化的 shell 兩者。

10. 常見問答集 (FAQ) 列表

Q. 我從我的 boot/root 磁片開機,但是什麼都跑不出來。我現在怎麼辦 ?

請看之前的 Troubleshooting 這節。

Q. Slackware/Debian/RedHat 的 bootdisk 如何運作 ?

請看之前的 What the pros do 這節。

Q. 我要如何以 XYZ 驅動程式製作一張開機磁片 ?

最簡單的方法是去從離你最近的 Slackware 映射站拿到一個 Slackware 的 kernel 。 Slackware 的 kernel 是一般的 (generic) kernel ,這些 kernel 企圖將許多設備的驅動程式儘可能地包含於其中,因此,假如你有一個 SCSI或IDE控制器,試試看,很有可能它的驅動程式會在 Slackware 的 kernel 當中。

找到 a1 目錄,並且依據你所擁有的控制器種類,選擇 IDE 或 SCSI 兩者之一的 kernel 。對所選擇的 kernel 檢視其 xxxxkern.cfg 檔,並且去了解這份 kernel 中所擁有的驅動程式。如果你想要使用的設備在這份列表中,那麼這個符合的 kernel 就應該能用來開機。下載 xxxxkern.tgz 檔,並且用之前在有關 making boot disks 的章節中所描述之方法, copy 它到你的開機磁片中。

然後你必須檢查在 kernel 中的 root 設備,使用 rdev zImage 這個指令。接著 rdev 將顯示目前在 kernel 中的 root 設備。如果這和你所想要的 root 設備不同,那麼使用 rdev 改變它。舉例來說,我試的 kernel 設定到 /dev/sda2 ,但是我的 root SCSI partition 是 /dev/sda8 。為了能使用 root 磁片,你將必須使用這個指令 rdev zImage dev/fd0/ 。

假如你還想知道如何 set up 一張 Slackware 的 root 磁片,這就已經超出這份 HOWTO 的範圍,所以我建議你查閱 Linux Install Guide ,或是設法取得 Slackware distribution 。詳情請看在這份 HOWTO 中,標題為 Reference 的章節。

Q. 我如何以新的檔案更新我的 root 磁片 ?

最簡單的方法是從 rootdisk copy 檔案系統回你所使用的那個 DEVICE (從之前的 Creating the filesystem 這節而得的)。然後掛上這個檔案系統並且進行改變動作。你必須記住你的 root 檔案系統從哪裡開始,以及它佔了多少 block:

在完成改變之後,如同之前一樣進行下去 (在 Wrapping it up 這節中) ,並且把 root filesystem 傳送回那張磁片上。如果你並沒有改變新的 root filesystem 的啟始位置,你應該不用再重傳 kernel ,或是重新計算 ramdisk 的 word。

Q. 我要如何移除 LILO ,好讓我能再用 DOS 開機 ?

這個問題並非真的是 Bootdisk 的一個主題,只是這個問題常常被問到。在 Linux 的環境下,你可以執行:

你也可以使用 dd 這個指令把被 LILO 所儲存的備份, copy 到開機磁區上。如果你想要這樣做,請參考 LILO 的文件。

在 DOS 與 Windows 的環境下,你可以使用這個 DOS 指令:

MBR 是 Master Boot Record(主要開機記錄)的縮寫,它會用一個乾淨的 DOS 開機磁區,替換原本的開機磁區,而且這個動作不會影響 partition table 。一些有潔癖的人 (purists) 並不同意這一點,可是就連 LILO 的原作者, Werner Almesberger ,都同意此作法。這個作法簡單,而且有用。

Q. 如果我遺失了我的 kernel 與 我的開機磁片,我要如何開機 ?

如果你並沒有一張已準備好的開機磁片,最簡單的作法可能是要依照你的磁碟控制器類型 (IDE 或 SCSI) 取得一份 Slackware kernel ,如同之前所述的 `我如何用XXX驅動程式製作一張開機磁片 ?' 。然後你就可以用這個 kernel 開機,接著修理有損壞的地方。

你取得的 kernel 可能沒有與你想要的磁碟種類和 partition 相對應的 root 設備集。舉例來說, Slackware 的 generic SCSI kernel 有與 /dev/sda2 相對應的 root設備集,然而,我的 root Linux partition 是在 /dev/sda8 。在此情況下, kernel 中的 root 設備將必須被改變。

你仍然可以改變 kernel 的 root 設備與 ramdisk 的設定,縱使你手上只有一個 kernel 和某種其它的作業系統,像 DOS 。

rdev 藉著改變在 kernel 檔案裡,在固定位移位置 (offset) 上的值,來改變 kernel 的設定,因此,如果你手上有一個 hex 編輯器 (on whatever systems you do still have running) ,你可以完成相同的事 -- 例如在 DOS 環境下的 Norton Utilities Disk Editor 。接著,你需要進行檢查,如果必要的話,你得改變 kernel 檔案裡,在以下位移位置上的值:

關於 ramdisk word 之解釋,寫在之前的 Setting the ramdisk word 這節裡。

Major 與 minor 設備號碼必須設成你想要掛你的 root filesystem 於其上的設備。一些可供選擇的有用參考數值如下:

一旦你設定了這些值,接下來你可以將這個檔案寫入一張磁片內,你可以利用 Norton Utilities Disk Editor ,不然就是利用名為 rawrite.exe 的這支程式。這支程式在所有的 distribution 都找得到。這支程式是一支在DOS環境下執行的程式,它能將檔案寫入一張 raw disk ,從開機磁區開始寫入,而不是將檔案寫入檔案系統。如果你使用 Norton Utilities ,你必須將檔案寫入一張實體磁片,從磁片的頭開始寫入。

Q. 我要如何製作 boot/root 磁片的額外備份 ?

因為磁性媒介可能在一段時間後遭遇損害,你應該保留幾張你的救援磁片的備份,以防原來的那一片不能被電腦讀取。

製作任何磁片的備份,包括開機用與公用程式 (utility) 磁片,最簡單的方法是利用 dd 這個指令,去 copy 原來那張磁片的內容到你硬碟上的一個檔案之中,然後再用相同的指令將這個檔案 copy 回一張新磁片上。請注意,你並不需要,也不應該去 mount 這張磁片,因為 dd利用raw設備介面。

要 copy 原磁片,請輸入以下指令:

在此, DEVICENAME 是指這台磁碟機的設備名 (譯按:/dev/fd0) ,而 FILENAME 是指(存在硬碟上的)輸出檔案檔名。省略 count 參數讓 dd 去copy整張磁片 (如果是高密度磁片,有 2880 個 blocks) 。

要把從上面得到的檔案 copy 到一張新磁片上,請插入一張新磁片並輸入相反的指令:

請注意,以上的討論是假設你只有一台軟碟機。假如相同種類的軟碟機你有兩台,你可以利用像下面的指令去 copy 磁片:

Q. 我如何能在每一次開機時,不用輸入 “ahaxxxx=nn,nn,nn” ?

當一台磁碟設備不能被自動偵測時,就有必要提供 kernel 指定的設備參數字串,諸如:

這行參數字串可以利用 LILO 以數種方法提供給 kernel :

舉例來說,一行使用上述參數字串的樣本命令列將長成這樣:

如此將會傳遞設備參數字串給 kernel ,同時也要求 kernel 把 root 設備設定到 /dev/sda1 ,並且儲存整行命令列,讓以後開機時都能再使用這個命令列。

以下是一個 APPEND 敘述的樣本:

請注意參數字串在命令列上 不能 被雙引號夾住,但是參數字串在 APPEND 敘述中 一定要 被雙引號夾住。

另外也請注意,為了能讓參數字串起作用, kernel 內必須有符合這個磁碟類型的驅動程式。如果沒有,那麼就沒有東西會去接受 (listen for) 這個參數字串,所以你將必須重新建造一個包含指定驅動程式的 kernel 。有關重新建立 kernel 的細節,請至目錄 /usr/src/linux 閱讀其 README 檔,以及 Linux FAQ 與 Installation HOWTO 。 Alternatively ,你可以為這種磁碟類型取得一個 generic kernel 並且安裝它。

在體驗 LILO 安裝之前,強烈建議讀者先讀過 LILO 文件。不小心使用 BOOT 敘述將會損壞 partition 。

Q. 在開機的時候,出現了 “A: cannot execute B” 的錯誤訊息。為什麼 ?

程式名稱有好幾種不同的寫法被寫死 (hardcoded) 在不同的公用程式裡。這些寫法不會在每個地方都發生,但是它們可能說明了為什麼一個顯而易見的可執行檔,不能在你的系統上被發現,縱使你看到它就在那裡。你可以找出是否一個已知的程式有另一種被寫死的名稱,你可以利用 strings 這個指令,並且利用管道方法 (譯按: piping, | ) 將輸出透過 grep 呈現出來。

已知關於寫死的例子有:

為了修正這些問題,不是移動這些程式到正確的目錄,就是更改設定檔 (e.g. inittab)以指向正確的目錄。假如有所懷疑,就請先把程式如同它們在你硬碟上一樣,放入相同的目錄,並且如同它們顯現在你硬碟上一樣,使用相同的 inittab 與 /etc/rc.d 檔。

Q. 我的 kernel 支援 ramdisk ,但是卻初始化 0K 的 ramdisk 。為什麼 ?

當 kernel 正在進行開機動作時,在問題發生之處,會出現一個像這樣的 kernel 訊息:

這可能是因為 size 已被 kernel 參數在開機時設成 0 。這可能是由於一個 overlooked LILO組態設定檔參數所導致:

在某些較舊的 distributions 裡,這個會被包含在 LILO 組態設定檔樣本中,這放在那裡是為了 override 任何 kernel 原先的設定。如果你有這樣的一行,請移除之。

請注意,如果企圖使用一個已被設定成 0 size 的 ramdisk ,這樣的行為將會導致不可預測的結果,同時也會讓 kernel 不知如何是好。

11. 資源與指示

當拿取一個套件時,除非你有好的理由,否則請一定要拿最新的版本。

11.1. 預先做好的 Bootdisks

這些是 distribution bootdisks 的來源。 請選擇映射站台下載以減少這些主機的負荷。

除了 distribution bootdisks 以外,也可以得到以下的救援磁片映像檔。除非有另外特別指定,否則這些都可在 http://metalab.unc.edu/pub/Linux/system/recovery/!INDEX.html 的目錄中找到。

11.2. 救援套件

目前可以從 metalab.unc.edu 取得數種製作救援磁片的套件。利用這些套件,你可以指定包含一組檔案,接著軟體就會自動地進行 bootdisk 的製作 (自動化程度會有所不同)。請看 http://metalab.unc.edu/pub/Linux/system/recovery/!INDEX.html 以取得進一步的資訊。

請仔細檢查檔案日期 。一些套件有數年未被更新,而這些套件將無法支援「載入至 ramdisk 之壓縮 root filesystem 」的製作。就目前所知, Yard 是唯一可支援此的套件。

11.3. LILO -- the Linux loader

由 Werner Almesberger 撰寫。一個優秀的 boot loader ,其文件包含了開機磁區內容的資訊,以及開機流程的初期階段。

11.4. Linux FAQ 與 HOWTOs

這些文件可以從諸多來源中取得。這些文件可以從諸多來源中取得。請見 usenet 新聞論壇 news.answers 與 comp.os.linux.announce。

這些 FAQ 可以從 http://linuxdoc.org/FAQ/Linux-FAQ.html 中取得,而 HOWTOs 可以從 http://linuxdoc.org/HOWTO/HOWTO-INDEX.html 中取得。大部分 Linux 文件可以在 The Linux Documentation Project homepage 中找得到。

11.5. Ramdisk使用方法

有關新的ramdisk 程式碼如何運作的完整敘述,可以在隨附於 Linux kernel 的文件中找到。請看 /usr/src/linux/Documentation/ramdisk.txt 。這份文件是由 Paul Gortmaker 所編寫,同時包含了一節關於製作壓縮的 ramdisk 。

11.6. Linux開機流程

若想了解關於Linux開機流程的更多細節,以下有一些指示文件:

12. LILO boot error codes

有關這些錯誤碼的問題時常在 Usenet 上被人提到,所以我們以服務的心情將它們表列如下。這份摘要引用自 Werner Almsberger 的 LILO User Documentation

當 LILO 載入自己時,螢幕上會顯示 LILO 這個字。每一個字母 (letter) 會在執行某個特定動作之前或之後被印在螢幕上。如果 LILO 在某點上不能完成任務,到此為止所印出的字母可以用來辨認出發生了什麼問題。

(nothing)

L

LI

LIL

LIL?

LIL-

LILO

如果在 LILO 正試著載入 boot image 時, BIOS 發出一個錯誤訊號,那麼相對映的 (respective)錯誤碼會顯示出來。錯誤碼的範圍從 0x00 到 0xbb 。請看 LILO User Guide for an explanation of these 。

13. Root filesystem 列表樣本

14. 工具程式磁片 (utility disk) 目錄列表樣本

LinuxBootdiskHowto (last edited 2007-02-17 03:12:35 by CaseyBournazian)