2011年7月21日 星期四

我的客製化光碟

作者: Baron. Wan



    在網路上, 只要你打個 linux 客製化 光碟 的字樣, 搜尋引擎就會幫你找出一堆, 但實做起來常感到落東落西的, 而且我就一直覺得, 難道沒有比較方便的做法, 或是如果能夠將它標準化, 其實我在兩年前就做過這樣的研究, 當時也寫了自動化的 script 讓它可以產生出真正自己要的安裝光碟, 不過當時的研究花的時間頗長, 之後又沒有做完善的注釋, 以至於兩年後的今天, 原以為我自離開那家公司後, 可能很難有機會再用到了....不過因為腦袋有著之前的研究紀錄, 關鍵的地方它都幫我一一標註, 所以我只花了少許的時間, 一方面再次確認與之前的記憶是否更新或衝突, 另一方面則是再次著手撰寫 shell script, 以便於日後客製化的過程, 但是很抱歉的是, 在這裡我是不會將 shell script 一一公布, 因為那是我自己花時間研究的, 同時我認為給魚吃, 不如教會怎麼釣魚, 雖然我有個朋友每次都苦口婆心的傳授我一些釣魚的訣竅, 不過可能要等我上心了, 我才會想去好好了解,...哈哈, 話題說遠了, 現在, 來體會這個經過我邏輯化的製作過程吧....呵呵 (^^)

    我就不說過去的光碟格式內容了, 因為那已經是過去, 隨著時間也將淹沒掉, 目前我測試的系統是 SL6 Linux, 或是 fedora 大概 10版以後是一樣的吧, 沒去考究它, 不過就算不一樣, 也只是增加/減少 hdlists 的這個檔案吧. 我測試的這個系統(SL6), 還真是進化了! Install 時不但有 mini (base) 系統環境可選擇, 而且它可是我看到目前安裝完 Linux 後, 最節省系統資源的一套OS了, 真的是好東西呀!! ^^, 只是, 習慣 RHEL 或 CentOS 的使用者們, 剛開始接觸它會有一點點的不適應感吧, 畢竟我感覺它是介於 Fedora 與 EL 之間呢. 好了, 我廢話很多, 哈哈哈....進入主題.

    請先安裝好一個最基本的系統, 這個系統安裝好之後一定不大, 然後第一步我們先查看系統內安裝了哪些套件, 經由原光碟, 我們將這些套件取出, 我會先放在一個叫 /rpms/rpmsource/ 的目錄中.

    接下來第二步, 我們可以利用 yum, 先將偵測到可 update 的套件, 複製一份到...我叫他 /rpms/rpmupdate/ 目錄中, 集中存放; 然後我要將 /rpms/rpmupdate/ 與 /rpms/rpmsource/ 做比較: /rpms/rpmupdate/ 中有 /rpms/rpmsource/ 中也有該套件的話呢, 由 /rpms/rpmsource/ 中做刪除的動作, 之後確定兩個目錄的內容沒有重複的套件存在. (為何要從 /rpms/rpmsource/ 做刪除呢? 因為 rpmsource/ 內容是原生套件, 也就是舊的, 而 rpmupdate/ 是由 yum update download 下來的, 所以是新的, 如果套件一樣, 當然是把舊的砍了, 留下新的 !! )

    第三步開始, 我們想要製作什麼樣的客製化內容? 就利用 yum 去找, 去安裝, 然後複製一份, 記得是連同相依性的套件, 一起放到 /rpms/rpmsource/ 中, 這過程可能會花較久的時間, 有時候 yum 上沒有, 就要去拜託 G神幫忙, 然後抓下來先安裝, 確定相依性問題...等等. 集合起來後, 我們的 /rpms/rpmsource/ 內容就越來越豐富了.

    接下來是個人習慣了...我先將光碟內容, 完整複製一份到 sl6iso/ 的目錄中, 然後又複製 sl6iso/ 給 custiso/, 目前這兩個目錄內容看起來是一樣的, 漸漸的, 我們要讓他不一樣!

    在 custiso/ 中, 將 Packages/ 和 repodata/ 這兩個目錄內容--[清空], 然後我們把上面1~3步所完成的 rpmsource/ 跟 rpmupdate/ 內的所有套件, 全部, 都複製到 /custiso/Packages/ 中, 現在, /custiso/Packages/ 內的所有套件都是你需要的了.

    接下來這個動作就重要了, 錯誤的話, 光碟不會安裝任何套件, 而且還會跳出錯誤訊息 要求你重新開機.

    comps.xml 這個檔, 網路上也很多人在說明它的格式, 不過自己還真是覺得越參考越亂 (= =|||), 最簡單, 最直接的方式, 就是把原光碟內(sl6iso)中的 repodata/comps.xml 點開來看裡面內容, 它是 xml 檔, 所以前面兩行的抬頭...很重要! 所有的內容都包覆在 [comps] 當中, 仔細看查閱就會發現, 每個主題 [id] 都用一個 [group] 包起來, 無論如何, 系統一定會去找這三個主題: core, base, buildsys-build; [name] 是給人看得, [id] 是給系統看的, 這樣說就懂了吧!! 其次是 [default] 不管原先是 true 還是 false, 在 base 中我一律是給它 true; [uservisiable] 是使用者看不看的見? 自己思考吧 (^^)...呵呵, 可 true 可 false;

    [packagelist] 內容包著就是我們最需要的擺放的套件名稱 [packagereq] 了, 在 [packagereq] 中有幾個參數: optional, mandatory, default, 我會將 optional 換成 mandatory; 上述 comps.xml 的說明, 個人覺得相當重要, 因為接下來要做的事情跟它有直接關係, 不要小看了這個檔, 很多人都需要費一番工夫來研究!!

    我要說的是: comps.xml 只需要以這三個 (core, base, buildsys-build) 為主的 [group], 其他的, 都刪了吧! 而 core 跟 buildsys-build, 其中 buildsys-build 的內容是需要的, 因為它內容所指的 package 都是在建構系統時會需要的命令, 而且你會發現其 type 值都是 mandatory. 至於 core, 因為我在 base 中, 會將所有需要的套件, 一次放在這裡, 所以 core 只需要留個樣子給系統看就行了! 知道我說的意思嗎? 就是只需要這樣做:


[group]
  [id]core[/id]
  [name]this is a core program[/name]
    [default]true[/default]
    [uservisiable]false[/uservisiable]
    [packagelist][/packagelist]
[/group]

注意, 在這裡我沒辦法用正常的 xml 來標示"<>", 所以改用"[]"替代.

我怎麼才能知道 [packagereq] 內對應的套件名稱是啥? 很簡單, 舉個 rpm 套件包: php-mbstring.1.34-1.i386.rpm (假設有此套件), 則套件名稱就是 php-mbstring, 對於套件解析的語法可以用 "-[0-9]." 取這之前的字串作為套件名稱, 而我們有很多個套件要放入....是不是很暈?!! shell script 可以幫我們達到我們要的. 例如:
for fs in `ls`
do
echo $fs|awk -F'-[0-9].' '{print $1}'
done

還記得剛剛複製的那個目錄 sl6iso/ ?!
那個目錄就是這時候用上啦! 你必須編寫一個 script, 它能夠以 sl6iso/repodata/comps.xml 這份完整的內容為藍圖, 針對 custiso/Packages/ 內我們所需要的套件, 自動產生套件名稱, 同時先格式化客製化一份新的 comps.xml, 然後將這些套件名稱, 依依的放入 [packagereq] 所屬的標籤欄位中, 從而產生出如下的樣式內容:

PS. 完成之後的 comps.xml 應該是像這樣:
[comps]
    [group]
        [id]core[/id]
        ....
    [/group]

    [group]
        [id]buildsys-build[/id]
        ....
        [packagelist]
            [packagereq type="..."]...[/packagereq]
            ...
        [/packagelist]
    [/group]

    [group]
        [id]base[/id]
        ....
        [packagelist]
            [packagereq type="default"]php-mbstring[/packagereq]
            ....
        [/packagelist]
    [/group]
[/comps]
如果你真的自己撰寫好了一支可以完整呈現如上的架構跟實際你需要的內容, 恭喜你, 以後就靠它行走江湖了...哈哈.

    產生了我們需要的客製化 comps.xml 後, 我們先複製它到 custiso/repodata/, 然後產生 comps.xml.gz, 再複製它到 custiso/repodata/ 中; 這時的 custiso/repodata/ 有兩個檔: comps.xml 與 comps.xml.gz, gz 怎麼產生不用我解釋吧?!! gzip comps.xml 就是了.

    實做到這裡, 告訴你一個好消息, 快完成了! 真的, 就差臨門一腳!! 興奮吧 (^^).

    進入 custiso/ 中, 這時我們底下其中有兩個目錄: repodata/ 與 Packages/, 在現在的這個位置執行:
createrepo -g 完整路徑+comps.xml(/var/opt/custiso/repodata/comps.xml) ./
然後 createrepo 就會自動針對其下的 Packages/ 內的套件分析, 先後在 repodata/ 內產生新的資料檔.

    如過程中沒有錯誤, 恭喜你, 完成了人生中最重要的一步! 接下來編寫 ks.cfg, 可利用 kickstart 套件, 另外, isolinux/isolinux.cfg 中也需要添加 ks.cfg 的紀錄, 最後轉成 .iso 檔, 它就會是完全自動安裝的客製化光碟.

[註一] 如果套件須持續的保持更新, 那麼接下來, 我們需要另行規劃一支 scrpit 來運行 : 針對原來舊有的套件做更新的動作, 可利用 yumdownloader 來達成, 但過程中我們需要判斷該套件是否有新的套件, 若有則需要將舊有的套件刪除, 但有些套件可能是經由你自己修改後產生的, 可能與原先的會有大大的不同, 此時如果做 update 的話, 很可能會被其他 yum mirror 站台內該新的套件給取代, 這時你原先修改的內容將不復存! 這是我想的到的重要缺失, 同時我也針對該項問題, 想到了解決方案 :

    產生一個 list 檔, 內容是不想更動的套件名稱. 
        ex: php-mbstring-3.3.5-1.i686.rpm , 則紀錄 php-mbstring 該名. 因為這樣的名稱才能在 yumdownloader 指令中找到相對應的套件名稱.

    在 script 中提及 : 只要是套件名稱為 該 list 檔中所列, 則忽略不更新.

沒有留言: