專業rpm包製作神器multipkg介紹
前言
rpm 包是linux 上比較常見的軟體包組織格式;其安裝,升級,解除安裝過程都比較簡易,容易上手。
但是,由於rpm的靈魂-spec 檔案,其格式,語法不太容易理解,或者有些複雜,導致不少 SA, Pe 或者 開發人員,對於“晦澀”的 SPEC 檔案編寫卻敬而遠之,結果不少人就放棄了通過 rpm 去管理軟體包。轉而投靠 scp/rsync 檔案複製, tgz壓縮包,git,或者一股腦打包進docker 映象的方式來管理軟體。不管長江後浪如何來勢洶洶,經典的 rpm 格式軟體包依然是如今系統管理的主流軟體管理方式,今天仍然值得技術人員去研習,掌握。
multipkg 的出現
雖然鄙人曾編撰過一本《Linux 軟體管理平臺設計與實現》的技術書籍,其中以庖丁解牛的方式,大談特談了 rpm 是怎麼組成的,從協議組成,欄位,原始碼等等,把 rpm 大卸八塊,然後又把spec檔案,yum的原理等XX了一遍又一遍,覺得 rpm 和 yum 在我面前,基本已經體無完膚,搖搖欲墜,一覽無餘。 但是,時至今日,當有人來找我問我:我想搞個RPM,你幫我看下spec 怎麼寫?我依然會果斷的回覆:“我不會,自己搞去”。
確實是的,你不可能天天都記得 spec 怎麼寫,除非你是SCM同學,於是乎,我們開始尋找一種不需要spec 檔案的 rpm 製作方式(可能嗎?),或者有無能避開spec編寫的rpm製作工具? 答案不用猜,肯定是有的,那就是 multipkg(雅虎繫有很多好用而樸實的工具):
https://github.com/ytoolshed/multipkg
multipkg 的安裝
直接參考官方文件(注意,確保你的機器能連線到公網):
以下部署過程,在centos5,6,7 上都得到驗證。
git clone https://github.com/ytoolshed/multipkg.git
cd multipkg
yum install perl-YAML-Syck perl-ExtUtils-MakeMaker
PREFIX=./root PKGVERID=0 INSTALLDIR=source scripts/transform
perl -I ./source/lib root/usr/bin/multipkg -t .
sudo yum -y install multipkg-*rpm
rm multipkg*rpm
git-multipkg -b https://github.com/ytoolshed/ multipkg
sudo yum upgrade ./multipkg*rpm
注意:對於6u的系統,subversion-perl-1.6.11 這個依賴包不好找,需要關注下。
我們都知道,rpm 包從生成過程來比較,分為兩類:一類是需要原始碼編譯生成二進位制檔案的格式,另外一種是不需要原始碼編譯(直接壓縮原始碼)形成的軟體包;前者包括 c, java等語言開發的程式,而後者則是一些直接解釋,不需要編譯成中間程式碼的語言編寫的程式,比如shell,python或者ruby等
語言寫的程式。因此,本文,在講述multipkg的用法時,會介紹到這兩種不同生成過程的 rpm 包的構建方法。
multipkg 的工作原理
multipkg 並沒有按照 rpm 的格式去寫一個rpm檔案(《linux軟體管理平臺設計與實現》第一章中講到的協議),因為那樣做確實太複雜了,像其他工具一樣,multipkg在製作rpm格式的軟體包時,是基於rpmbuild命令來實現的。也就是說,準備好原始碼,spec檔案,然後放到合適的目錄中,呼叫rpmbuild命令,就編譯生成了rpm檔案。只不過multipkg把rpmbuild+spec檔案這種做包方式用的更優雅些,因為你不需要去關注spec檔案,也不需要去關注編譯rpm檔案的目錄,而只需要關注你的原始碼和編譯時hook指令碼即可。
multipkg工作的大致原理是:通過 index.yaml 檔案來提供SPEC檔案中的所有tag,比如name,version,require,config等資訊,然後通過scripts/目錄下的post.sh,pre.sh,postun.sh,preun.sh這四個指令碼,來儲存rpmbuild時在安裝前後,解除安裝前後執行的指令碼內容。最後,root目錄提供了rpm的檔案列表的一部分(因為scripts的指令碼中可能會動態建立檔案)。
source 或者原始碼壓縮包提供了原始碼。這時,構建rpm的因素就足夠了。spec 檔案由 index.yaml 檔案和scripts 構成。對於需要編譯類的工程,原始碼壓縮包或者source 目錄中的檔案提供了原始碼。
對於不需要編譯類的工程,root 中的檔案直接提供了rpm的檔案列表和安裝路徑。這樣,在編譯時,先通過index.yaml和scripts中的檔案替換spec檔案模板,生成該工程用的spec檔案,然後調整原始碼和spec檔案的目錄,呼叫 rpmbuild命令,作用於原始碼和spec檔案,就形成了rpm包。
multipkg 的目錄結構
對於需要編譯類的工程,一般就是 index.yaml,scripts/*.sh 和source目錄(或者原始碼包 xxx.tar.gz),例如repobuilder這個工程的目錄結構如下:
tree repobuilder/
repobuilder/
├── index.yaml
├── scripts
│ ├── build
│ ├── preun.sh
│ └── run
└── source
├── cmthread.c
├── colordefine.h
├── configserver.c
├── configserver.h
├── daemon.c
├── datadef.h
├── inihelper.c
├── inihelper.h
├── loghelper.c
├── main.c
├── Makefile
├── nethelper.c
├── nethelper.h
├── os_independent.h
├── repo.conf
└── tags
其中index.yaml的內容如下:
---
default:
name: repobuilder
requires:
- createrepo >= 0.4.11
summary: muti-thread tasks to update repo of yum server
version: `1.1.0`
release: `1`
group: `xx`
packager: `xxxxx`
license: `xxxxx`
#the multipkg do not support config file for rpm-->need update
keepopt:
- %config(noreplace) /etc/repo.conf
- %defattr(-,root,root)
- %attr(0777 nobody nobody) /etc/repo.conf
scripts/build 的內容如下:
#!/bin/sh
make clean || exit 1
make || exit 1
mkdir -p $DESTDIR/etc/service/repobuilder
mkdir -p $DESTDIR/usr/bin/
install repobuilder $DESTDIR/usr/bin/
install repo.conf $DESTDIR/etc/
又比如wget 工程的目錄結構如下:
tree wget/
wget/
├── index.yaml
├── root
│ └── etc
│ └── wget.conf
├── scripts
│ ├── build
│ ├── post.sh
│ └── preun.sh
└── wget-1.14.tar.gz
其中build的內容就是spec中build段的內容,如下:
#!/bin/sh
exec 2>&1 >/tmp/build.log
./configure --prefix=/usr/local/wget --with-ssl=openssl
make
make install
對於不需要編譯類的工程,就更簡單了,只需要在root目錄中放置你的檔案即可,比如 pkg-release 這個包就是如此:
tree pkg-release
輸出如下:
pkg-release
├── index.yaml
└── root
├── bin
│ └── pkgrelease
└── etc
└── pkgrelease.conf
執行命令:
multipkg pkg-release
後,生成檔案
pkgrelease-1.1.0-1.noarch.rpm
通過命令:
rpm -qpl pkgrelease-1.1.0-1.noarch.rpm
檢視該rpm檔案包含的檔案列表為:
/bin/pkgrelease
/etc/pkgrelease.conf
從上面的結構你應該已經看到了, 在原始碼目錄中,root目錄就類似於安裝機器的 “/” 目錄,這樣,在root下怎麼存放檔案,你的rpm將來就怎樣安裝到目標機器上去。
使用舉例
還是舉兩個例子,一個是原始碼編譯工程,一個是不需要編譯的指令碼構成的工程。
原始碼編譯工程
repobuilder 工程的目錄樹如下:
├── index.yaml
├── scripts
│ ├── build
│ ├── preun.sh
│ └── run
└── source
├── cmthread.c
├── colordefine.h
├── configserver.c
├── configserver.h
├── daemon.c
├── datadef.h
├── inihelper.c
├── inihelper.h
├── loghelper.c
├── main.c
├── Makefile
├── nethelper.c
├── nethelper.h
├── os_independent.h
├── repo.conf
└── tags
其中source 下的檔案就不再重點介紹,是一個標準的C工程,著重看下index.yaml和scripts中內容:
index.yaml:
---
default:
name: repobuilder
requires:
- createrepo >= 0.4.11
summary: muti-thread tasks to update repo of yum server
version: `1.1.0`
release: `1`
group: `xxxx`
packager: `xxxx`
license: `xxxx`
#the multipkg do not support config file for rpm-->need update
keepopt:
- %config(noreplace) /etc/repo.conf
- %defattr(-,root,root)
- %attr(0777 nobody nobody) /etc/repo.conf
能看到基本的資訊,name,version,release,requires等,requires可以寫多行,標示依賴多個包,
需要注意的是keepopt目前在multipkg中還不支援,這幾天我會參考以前的程式碼,嘗試把這個功能加進來。然後看下scripts中的檔案:
build:
#!/bin/sh
make clean || exit 1
make || exit 1
mkdir -p $DESTDIR/etc/service/repobuilder
mkdir -p $DESTDIR/usr/bin/
install repobuilder $DESTDIR/usr/bin/
install repo.conf $DESTDIR/etc/
很簡單,就是編譯,安裝。和spec檔案中內容一樣。
preun:
#!/bin/bash
if [ "$1" = "0" ]; then
rm /service/repobuilder || exit 1
/usr/local/bin/svc -dx /etc/service/repobuilder /etc/service/repobuilder/log || exit 1
fi
注意 “$1 = 0”這個判斷,在書中,已經說過,preun的第一個引數為0標示是解除安裝,否則是升級。
刪除安裝的服務目錄。
run:
multipkg中scripts/run這個指令碼比較特殊,是服務啟動指令碼,也就是自啟動指令碼,所以,只需要把你
的指令碼main函式,或者執行主體指令碼儲存為scripts/run即可,比如repobuilder的例子,或者,你也可以寫出如下的scripts/run:
#!/bin/bash
while true
do
sleep 5
date
done
都是可以的。當rpm安裝後,這個run的安裝路徑是:/etc/service/repobuilder/run 也就是說,scripts/run指令碼,會為每個想要自啟動的指令碼新增一個服務目錄,路徑為:/etc/service/xxx
這個動作,和“服務”這個說法比較一致,既然是“自啟動”,那麼就認為其為一個“服務(service)”,所以把
執行指令碼儲存在“/etc/service”下,這種設計比較人性化,容易理解。
指令碼/不需編譯類工程
這種工程比較簡單,只需要理解 root目錄的作用就OK了,看下pkgaudit這個工程的目錄結構和檔案列表,你應該就明白你的root目錄應該怎麼儲存了:
目錄結構:
tree pkgaudit/root/
pkgaudit/root/
├── etc
│ └── pkgaudit.conf
└── usr
└── local
└── pkgaudit
├── data
│ └── readme.txt
└── log
└── readme
檔案列表:
rpm -qpl pkgaudit/pkgaudit-1.0.0-3.noarch.rpm
/etc/pkgaudit.conf
/etc/service/pkgaudit/log/run
/etc/service/pkgaudit/run
/usr/local/pkgaudit/data/readme.txt
/usr/local/pkgaudit/log/readme
兩種情況都包括(原始碼編譯+指令碼類)
這類情況下,目錄結構也比較簡單,你可以認為是在原始碼編譯工程下面新增一個root目錄即可,不過這時,你的rpm中包含的檔案列表由兩部分組成:build安裝的檔案和root中包含的檔案。讀者可以自己測試這種情況,並且檢視最終生成的rpm包含的檔案列表資訊。
關於example
發現原 project 自帶的例子有些問題,就把我以前自己做的一個程式做了個example作為附件傳上來。
為了在例子中儘可能多的普及 multipkg 的用法和 rpm 的一些知識,我們在 index.yaml 檔案中寫了很多“無用的例子”,如下:
default:
name: tskeeper
version: `1.0.0`
release: `2`
packager: `anyone`
summary: `adding tskeeper as an example of multipkg`
group: ``
license: `public`
arch: `x86_64`
requires:
- procps
- daemontools
provides:
- tskeeper-examples
- mamimamihong-tskeeper
conflicts:
- other-task-keeper
- all-task-keeper
obsoletes:
- old-tskeeper
- taskeeper
files:
- "/etc/test_conf1.conf":
group: "root"
perm: "0666"
owner: "root"
- "/etc/test_conf2.conf":
group: "root"
perm: "0777"
owner: "nobody"
config: "no"
- "/etc/proclist.ini":
group: "root"
perm: "0666"
owner: "root"
config: "yes"
- "/var/doc/tskeeper":
group: "root"
perm: "0444"
owner: "root"
doc: "xxoo"
進入 tskeeper 目錄,當 multipkg 安裝好以後,你就可以自己製作包了:
multipkg .
tskeeper-1.0.0-2.x86_64.rpm
然後可以通過 rpm 的命令來查詢這個包的資訊,與 index.yaml 檔案對比:
# rpm -qp tskeeper-1.0.0-2.x86_64.rpm --provides
tskeeper
mamimamihong-tskeeper
tskeeper-examples
tskeeper = 1.0.0-2
tskeeper(x86-64) = 1.0.0-2
# rpm -qp tskeeper-1.0.0-2.x86_64.rpm --requires
procps
daemontools
/bin/sh
/bin/sh
rpmlib(FileDigests) <= 4.6.0-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(PayloadIsXz) <= 5.2-1
# rpm -qp tskeeper-1.0.0-2.x86_64.rpm --conflicts
all-task-keeper
other-task-keeper
# rpm -qp tskeeper-1.0.0-2.x86_64.rpm --obsoletes
old-tskeeper
taskeeper
關於docfiles 和 configfiles,在我自己的branch中增加了程式碼通過
config: “yes/no” 或者 doc:”yes/no”
來控制是否為doc或者config檔案,所以,在 tskeeper 例子中,通過作者原生 multipkg 生成的包,是看不到這些欄位控制產生的效果的。
文末說明
說明:如果沒看懂或者還有啥疑問,可以問我,或者買本我的書來學習《Linux 軟體管理平臺設計與實現》^_^
相關文章
- Linux自己製作rpm包Linux
- RPM包安裝與介紹
- 製作PHP的RPM包例項PHP
- Centos 7 製作MySQL 5.7 RPM包CentOSMySql
- 《RPM原始碼包的製作》RHEL6原始碼
- 使用CheckInstall從原始碼製作RPM安裝包原始碼
- Excel圖表製作方法介紹Excel
- CnPack IDE專家包介紹IDE
- jQuery外掛製作簡單介紹jQuery
- Excel分類軸介紹與製作Excel
- rpm命令的使用介紹
- linux作業系統介紹Linux作業系統
- RPM常用命令介紹
- RPM 的介紹和應用
- rpm常用命令及rpm引數介紹
- 如何製作一個 RPM 檔案
- 簡易rpm套件的製作(轉)套件
- 精通RPM之--製作篇(中)(轉)
- SAP作業型別應用介紹型別
- Linux作業系統介紹(轉)Linux作業系統
- 作業:自我介紹+軟工5問軟工
- CentOS中rpm命令詳細介紹CentOS
- 專業音樂製作軟體
- node.js非專業介紹Node.js
- 【動手開發作業系統】- 介紹作業系統
- Linux作業系統總體介紹!Linux作業系統
- 作業1:自我介紹+軟工5問軟工
- 作業一:自我介紹+軟工5問軟工
- pytorch 包介紹PyTorch
- 抖音GIF表情包製作教程 如何製作QQ動態表情包
- OpenSSH9.6p1的EL7版本rpm安裝包製作
- 零基礎創作專業wordpress網站01-課程介紹網站
- API 文件神器 Swagger 介紹及在 PHP 專案中使用APISwaggerPHP
- 聊聊畢業設計系列 --- 專案介紹
- 鬥圖神器–純前端實現視訊轉GIF製作表情包(已開源)前端
- Linux服務管理神器:SYSTEMD介紹Linux
- javascript閉包概念介紹JavaScript
- Springmvc jar包介紹SpringMVCJAR