Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

回顧

先前的壹、貳篇已經大概講述了一個 Linux 系統的基本要素,以及怎麼基於 tinycore linux 的 initrd 來製作自定義的 initrd。在這篇開始之前先來回顧一下。

首先,一個 Linux 系統包含兩個基本部分,程序和數據。程序是 Linux 內核,而數據就是初始的根文件系統。啟動一個 Linux 操作系統即是由引導器加載 initrd,以及命令行參數 cmdline,然後加載並調用 Linux 內核。雖然之前的例子裡直接使用 qemu 加載內核和 initrd,但其實其他啟動器(例如 GRUB)其實都是幹了相同的事情。

從源代碼編譯一個 Linux 內核是當然可以的。但對於製作一個發行版,怎麼寫系統文件以及提供什麼工具命令才是更為重要的。內核編譯的調參是屬於高級操作,是精益求精,在這之前我更注重先把基本框架描述好。

所以我們現在手頭擁有了這些概念和工具:

  • 內核
  • initrd
  • initrd 的解包和重打包
  • 軟件的下載
  • 用 qemu 直接加載系統調試

不斷手動重複這些操作對於人來說是繁瑣的,而且還容易出錯。這時最好就有一個你能輕易搞明白的程序幫你規範好這些操作,減少錯誤的發生、加速重複過程的執行。

規則是死的,人是活的;任何系統中最脆弱的環節一直都是人。 —— 斯·沃碩德

The tool

說了這麼多,終於到了說具體工具的時候了。

make-tinycore-linux 是我把第二篇中步驟細化完善後編寫出來的 shell 腳本工具。僅需要一個(可選的)build.rc 文件即可描述對 TinyCore initrd 的修改。原理十分簡單,但這裡我先介紹如何使用。

我們先規範一下目錄結構,設定工作目錄應該如下:

1
2
3
tinycore-build
|- bin
|- build.rc

其中 bin 存放著幫助你構建的簡單命令,而 build.rc 則是描述構建內容的文檔。

我們先來看看 build.rc 的樣例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 選擇 TinyCore 的版本號
# 參考 http://tinycorelinux.net/downloads.html
TC_VERSION=13

# 選擇 TinyCore 的架構
# 參考 http://tinycorelinux.net/TC_VERSION
TC_ARCH=x86_64

# 更改 TinyCore Linux 的倉庫地址
#TC_REPO="http://tinycorelinux.net/"

# 更改輸出目錄,默認是當前執行目錄
#BUILD_OUTPUT="$WORK_DIR"

# DOWNLOAD 是用於下載文件的 CURL 命令
# 更改 CURL_DOWNLOAD 的值以修改其行為
#CURL_DOWNLOAD="$CURL_DOWNLOAD "

# FETCH 是用於獲取遠端文本的 CURL 命令
# 更改 CURL_FETCH 的值以修改其行為
#CURL_FETCH="$CURL_FETCH "

# 緩存下載了的文件
CACHE_FILES=true

# 不要在構建完成後執行清潔鉤子
# 注意,如果開啟,則需要在每次構建前清理 build 目錄
# 否則構建會失敗
#DO_NOT_CLEANUP=true

# PACKAGES 包含需要被包含進 rootfs 的 tcz 包名字
# 參考 TinyCore 的倉庫
# 依賴會被自動拉取:D
PACKAGES=(
"bash"
"iproute2"
"fuse"
)

################################################################
additional_patchs() {
################################################################
# 針對 rootfs 的額外修改
# rootfs 在 $BUILD_DIR/rootfs 下
#
# PACKAGE_DIR 是包含已下載的軟件包的目錄
# BUILD_DIR 是構建目錄
# WORK_DIR 是工作目錄
#
################################################################
: 在這裡寫你的其他 rootfs 修改(建議不要刪掉這行喔)

################################################################
}
# END build.rc

相信熟悉 Linux 的人都知道,build.rc 是一個 shell 腳本。但可以些少點腳本來達到「安全地靈活」的目的,何樂而不為(畢竟是我幫忙寫和調試了嘛 XD)

現在我們有 build.rc 了,執行這個工具有兩種方式:

  1. 直接通過 curl 下載並喂給 bash(在 README 裡有寫)
  2. 先下載,然後執行(下載好之後建議放到 bin 目錄裡)

注意,因為修改、打包 rootfs 涉及到塊設備、字符設備以及權限維持等等的問題,這個工具必須要以 root 權限運行

以下假設你用的是第二種方式。那麼我們就直接執行:

1
sudo ./bin/make-tinycore-linux

你應該會看到一行行輸出提示它運行到哪了。成功結束後,產物就會出現在你指定的地方。

它會產生出一個 build 文件夾,裡面是構建時的緩存和中間產物。如果 DO_NOT_CLEANUP=true,連臨時文件都會出現在裡面。你可以借這個機制去觀察它的工作方式。但這樣的話,建議你每次構建前最好都手動刪掉整個 build 文件夾,我還沒讓這個腳本智能到在這種情況下依舊能自動刪除(或許以後的版本會有)。

添加點額外的修改

相信你應該會留意到那個顯眼的 additional_patchs。這裡提前說一下,它會在打包 initrd 之前,所有軟件合併到 rootfs 文件夾裡的時候

經歷過構建,我猜你現在的文件目錄結構應該是這樣的了

1
2
3
4
5
6
tinycore-build
|- bin
|- build.rc
|- build
|- vmlinuz
|- initrd.gz

在給 additional_patches 添加內容之前,建議你先創建一個 patches 目錄。

按照建議,patches 目錄應該模仿根文件系統的目錄結構。其內容會在打包 initrd 之前覆蓋到 rootfs 文件夾裡。舉個例子我們需要增加一個腳本 helloworld

1
2
3
4
5
6
7
8
9
tinycore-build
|- bin
|- build.rc
|- build
|- patches
|- bin
|- helloworld
|- vmlinuz
|- initrd.gz

僅僅只是塞一句話進去:

1
2
#!/bin/busybox ash
echo "Hello world! Now is: $(date)"

additional_patches 裡這樣寫:

1
2
3
4
# 拷貝內容到 rootfs 文件夾內
cp -Rp $WROK_DIR/patches/. $BUILD_ROOT/rootfs/
# 允許其被當作程式執行
chmod +x "$BUILD_ROOT/rootfs/bin/helloworld"

重新執行 ./bin/make-tinycore-linux,啟動虛擬機,輸入 helloworld,你應該就能看到 Hello World 以及一個日期時間了。

✅ 小提示:你可以在 build.rc 裡 source 額外的私人配置,或者額外的過程來幫助你做更複雜的構建。

不過我建議你的 shell 代碼應該要寫得夠簡潔夠清晰。比起其他編程語言,shell script 的可讀性還是不太好的。

當你的構建越來越複雜了,我希望你能用更高級的語言來實現ーー不过到那时候,你也应该不需要我的这个小工具了吧(:D

⚠️ Note: Don’t use Bash everywhere! ⚠️

Although Bash is universal and elegant to programmatically execute unix commands, and apply logic to them, it can quickly get cumbersome once you start doing complex things like working with floating point numbers or find yourself needing arrays or other sophisticated datastructures.
-- Bash scripting(wiki.ghpc.au.dk)

下回分解

我是很樂意分享這個工具的工作流程的,畢竟還是翻了不少資料、溫習補習了很多工具指令和 shell 特性之後造出來的「作業」。我希望它以十分簡單的方式工作,也希望它的代碼能比較簡單。

所以下一章將會講 make-tinycore-linux 的工作流程

下一篇:「Linux 玩耍記事」製作一個發行版·肆:make-tinycore-linux

评论