要想制作RPM格式的軟件包,需使用如下命令格式:
rpm-bX[制作選項1制作選項2...]描述文件1描述文件2...
注:-bX可用-tX替換,效果有所不同:使用-b時,需要在命令行上指定軟件包描述文件;而使用-t時,在命令行上需要指定的不是軟件包描述文件,而是含有此描述文件的TAR格式的包裹文件(必須用gzip壓縮),RPM在准備制作軟件包時,會自動從此包裹文件中提取描述文件,根據其中的建包指令,生成RPM格式的軟件包。注意:此描述文件必須以.spec為後綴,其中必須有Source域,並且此域定義的源程序包必須存放在當前目錄下,否則的話,RPM將報錯退出。
注意,-bX與-tX當中的X,取不同的值時,RPM將執行不同的操作:(下面各個例子均對LZE的描述文件lze-6.0-2.spec進行操作,有的則通過管道技術,用nl命令給輸出加上行號,以便解釋)
1)X=p時,指示RPM執行描述文件中的預處理段(%prep)的腳本程序。該腳本程序一般用來解壓源程序包,並且為源程序打補丁,升級源程序。
#rpm-bplze-6.0-2.spec2>&1|nl
1Executing:%prep
2+umask022
3+cd/usr/src/dist/BUILD
4+echo'預處理腳本程序(prep)開始執行'
5預處理腳本程序(prep)開始執行
6+cd/usr/src/dist/BUILD
7+rm-rflze-6.0
8+/bin/gzip-dc/usr/src/dist/SOURCES/lze-6.0-2.src.tgz
9+tar-xvvf-
10drwxr-xr-xroot/root02001-11-0216:02lze-6.0/
11-rw-------root/root2462262001-11-0216:00lze-6.0/lze.c
12-rw-------root/root982492001-11-0216:00lze-6.0/lzeime.wb.c
13-rw-------root/root3399022001-11-0216:00lze-6.0/lzeime.py.c
14-rw-r--r--root/root12832001-11-0216:00lze-6.0/funkey.def
15-rwxr--r--root/root2502001-11-0216:00lze-6.0/inputme.def
16-rw-r--r--root/root8132742001-11-0216:00lze-6.0/wbzc.dat
17-rw-------root/root4742001-11-0216:02lze-6.0/makefile
18+STATUS=0
19+'['0-ne0']'
20+cdlze-6.0
21++/usr/bin/id-u
22+'['0=0']'
23+/bin/chown-Rhfroot.
24++/usr/bin/id-u
25+'['0=0']'
26+/bin/chgrp-Rhfroot.
27+/bin/chmod-Rfa+rX,g-w,o-w.
28+exit0
#
注:本例中第1行顯示的"Executing:%prep"表明RPM開始執行預處理段的腳本程序。例中行號後那些以加號(+)開始的行均為預處理段腳本程序的指令,其它內容則為指令執行所輸出的結果。從預處理段腳本程序所執行的指令,我們就可以看出RPM正在做什麼:
第2行:設置文件創建掩碼;
第3行:轉到RPM默認的編譯目錄;
第4行:回顯字符串,這才是用戶所寫的預處理段腳本程序的開始,第2,3行均是RPM增加的指令;
第6-27行:為%setup所擴展出來的指令及其執行結果,其中可以看到RPM用gzip命令解壓LZE的源程序包(第8行),而後用tar命令展開源程序包(第9行)。
第28行:正常退出,返回值為0。
2)X=l時,指示RPM檢查文件段(%files),看其中的文件是否存在。如果不存在,則RPM會報錯退出。
#rpm-bl-vvlze-6.0-2.spec|nl
1Processingfiles:lze
2D:File0:0100644root.root/etc/funkey.def
3D:File1:0100644root.root/etc/inputme.def
4D:File2:0100644root.root/usr/doc/lze-6.0-2/README
5Filenotfound:/usr/doc/lze-6.0-2/LICENSE
6D:File3:0100555root.root/usr/bin/lze
7D:File4:0100511root.root/usr/bin/lzeime.py
8D:File5:0100511root.root/usr/bin/lzeime.wb
9D:File6:0100644root.root/etc/wbzc.dat
10Provides:lze-edit
11PreReq:/bin/sh
12Requires:/bin/sh
#
注:本例命令中使用了通用選項-vv,以輸出RPM檢查時的調試信息(以行號和D:開始的行)。
由上看出,RPM對文件段的所有文件逐一進行檢查,找到的文件顯示其權限,屬主和屬組信息,結果發現/usr/doc/lze-6.0-2.LICENSE文件不存在,於是報出錯誤(File not found)(見第5行)。RPM在檢查過文件後,還顯示出描述文件要求LZE提供的功能(Provides)和所需的功能(Requires)。
3)當X=c時,指示RPM依次執行預處理段(%prep),編譯段(%build)的腳本程序。編譯段的腳本程序用來編譯連接軟件的源程序,生成可執行程序,通常一個make命令足夠。因為一個有良好習慣的程序員會把Makefile(程序維護文件)寫好,以便其它程序員編譯該軟件。如果某個軟件沒有維護文件的話,用戶要麼自己寫個Makefile,要麼在編譯段裡寫上軟件編譯與連接的各項命令。
4)當X=i時,指示RPM依次執行預處理段(%prep),編譯段(%build)和安裝段(%install)的腳本程序。安裝段的腳本程序的任務是將編譯連接好的執行程序拷貝到適當的目錄(如/bin,/usr/bin等公共執行目錄),以便打包或執行。它通常執行的指令是make install。
5)當X=b時,指示RPM依次執行預處理段(%prep),編譯段(%build),安裝段(%install)的腳本程序,之後根據文件段(%files)的文件列表,將文件打包,生成RPM執行程序包,最後執行清理段(%clean)。
#rpm-bblze-6.0-2.spec2>&1|nl
1Executing:%prep
2+umask022
3+cd/usr/src/dist/BUILD
4+echo'預處理腳本程序(prep)開始執行'
5預處理腳本程序(prep)開始執行
6+cd/usr/src/dist/BUILD
7+rm-rflze-6.0
8+tar-xvvf-
9+/bin/gzip-dc/usr/src/dist/SOURCES/lze-6.0-2.src.tgz
10drwxr-xr-xroot/root02001-11-0217:04lze-6.0/
11-rw-------root/root2462262001-11-0216:00lze-6.0/lze.c
12-rw-------root/root982492001-11-0216:00lze-6.0/lzeime.wb.c
13-rw-------root/root3399022001-11-0216:00lze-6.0/lzeime.py.c
14-rw-r--r--root/root12832001-11-0216:00lze-6.0/funkey.def
15-rwxr--r--root/root2502001-11-0216:00lze-6.0/inputme.def
16-rw-r--r--root/root8132742001-11-0216:00lze-6.0/wbzc.dat
17-rw-------root/root4742001-11-0216:02lze-6.0/makefile
18-rw-r--r--root/root12552001-11-0217:04lze-6.0/getinputme.c
19+STATUS=0
20+'['0-ne0']'
21+cdlze-6.0
22++/usr/bin/id-u
23+'['0=0']'
24+/bin/chown-Rhfroot.
25++/usr/bin/id-u
26+'['0=0']'
27+/bin/chgrp-Rhfroot.
28+/bin/chmod-Rfa+rX,g-w,o-w.
29+exit0
30Executing:%build
31+umask022
32+cd/usr/src/dist/BUILD
33+cdlze-6.0
34+echo'編譯連接腳本程序(build)開始執行'
35編譯連接腳本程序(build)開始執行
36+make
37cc-fwritable-strings-DUSE_AS_LZE-DFOR_LINUX-s-I/usr/zzz/src/include-DFOR_LZE_INPUTME-olze/usr/zzz/src/li-
38bsrc/mycurses.clze.cgetinputme.c/usr/zzz/src/my.a
39cc-DFOR_LINUX-s-I/usr/zzz/src/include-olzeime.wbgetinputme.clzeime.wb.c/usr/zzz/src/my.a
40lzeime.wb.c:Infunction`do_service':
41lzeime.wb.c:1409:warning:passingarg5of`bsearch'fromincompatiblepointertype
42cc-DFOR_LINUX-s-I/usr/zzz/src/include-olzeime.pygetinputme.clzeime.py.c/usr/zzz/src/my.a
43+exit0
44Executing:%install
45+umask022
46+cd/usr/src/dist/BUILD
47+cdlze-6.0
48+echo'安裝腳本程序(install)開始執行'
49安裝腳本程序(install)開始執行
50+makeinstall
51installing...
52done
53+exit0
54Processingfiles:lze
55FindingProvides:(using/usr/lib/rpm/find-provides)...
56FindingRequires:(using/usr/lib/rpm/find-requires)...
57Provides:lze-edit
58PreReq:/bin/sh
59Requires:/bin/shld-linux.so.2libc.so.6libc.so.6(GLIBC_2.0)libc.so.6(GLIBC_2.1)
60Wrote:/usr/src/dist/RPMS/i386/lze-6.0-2.i386.rpm
61Executing:%clean
62+umask022
63+cd/usr/src/dist/BUILD
64+cdlze-6.0
65+echo'建包結束後清理腳本程序(clean)開始執行'
66建包結束後清理腳本程序(clean)開始執行
67+exit0
#
注:本例中,各行解釋如下:
第1行:顯示RPM開始執行預處理段(%prep);
第2-29行:為預處理段(%prep)腳本程序執行的命令與結果,命令前有加號(+),結果前面則沒有。預處理完成了LZE源程序包的解壓縮(gzip-dc)與包的展開(tar-xvvf),從而為源程序的編譯打下了基礎;
第30行:RPM表示開始執行編譯段(%build);
第31-43行:為編譯段(%build)腳本程序執行的命令與結果。腳本程序執行的make維護命令,該命令執行了cc編譯程序,以編譯與連接LZE軟件;
第44行:RPM表示開始執行安裝段(%install);
第45-53行:為安裝段(%install)腳本程序執行的命令與結果。本段程序執行了makeinstall命令,將LZE的執行程序等文件拷貝到系統目錄下;
第54行:RPM顯示:開始處理LZE的文件(為%files文件段的內容);
第55-59行:RPM利用/usr/lib/rpm/find-provides程序查找LZE提供的功能,又利用/usr/lib/rpm/find-requires查找LZE所依賴的功能,以設定LZE的依賴關系;
第60行:制作完成LZE執行程序包,文件名為lze-6.0-2.i386.rpm,在/usr/src/dist/RPMS/i386目錄下;
第61行:RPM顯示:開始執行清理段(%clean)腳本程序,本段程序用於清理臨時文件;
第62-67行:為清理段(%clean)腳本程序執行的命令與結果。
從上我們可以清楚看出RPM制作軟件包的工作流程:預處理段,編譯段,安裝段,軟件包制作,清理段。
6)當X=s時,指示RPM建立源碼包。RPM源碼包的內容包括軟件包描述文件(SPEC),軟件源程序,軟件補丁程序,圖標文件等幾項。建立源碼包不需要執行軟件包描述文件中的各個功能段,僅需將所需文件包含到包中即可。
#rpm-bslze-6.0-2.spec
Wrote:/usr/src/dist/SRPMS/lze-6.0-2.src.rpm
#rpm-qplv/usr/src/dist/SRPMS/lze-6.0-2.src.rpm
-rw-------rootroot206711月215:44lze-6.0-2.spec
-rw-r--r--rootroot53870611月217:05lze-6.0-2.src.tgz
#
注:本例中,使用rpm-bs命令生成了LZE源碼包lze-6.0-2.src.rpm(在RPM標准源碼目錄/usr/src/dist/SRPMS下),然後用rpm -qplv命令查詢源碼包中所含的文件信息,從中可以看到LZE源碼包中有兩個文件:一個是軟件包描述文件lze-6.0-2.spec,一個是LZE源代碼包lze-6.0-2.src.tgz(TAR打包再用gzip壓縮),此文件由描述文件中的Source域確定。
7)當X=a時,指示RPM依次執行預處理段(%prep),編譯段(%build),安裝段(%install)腳本程序,之後先生成RPM源碼包,再根據文件段(%files)的文件列表,將文件打包,生成RPM執行程序包,最後執行清理段(%clean)腳本程序,清除中間文件。此命令執行的結果相當於先執行rpm-bs命令生成源碼包,再執行rpm-bb命令生成執行碼包。
選項列表
選項詳解
通用選項的解釋見<<精通RPM之二--安裝篇>>,本文不再贅述。
1.--short-circuit:單步執行
此選項的目的在於單步執行功能段,僅適用命令為RPM-bc(或-tc)和-bi(或-ti)時。當用rpm-bc--short-circuit命令時,RPM將不再執行預處理段(%prep)的腳本程序,直接執行編譯段(%build)的腳本程序。當用rpm-bi--short-circuit命令時,RPM將不再執行預處理段(%prep)和編譯段(%build)的腳本程序,僅執行安裝段(%install)的腳本程序。
為什麼要使用這個選項?其原因可能是源程序包中的文件有問題,導致RPM在編譯或安裝過程中出現了這樣或那樣的錯誤,如不能單步執行,則無法排除這些錯誤。單步執行後,用戶可以進入源程序所在的目錄,查看源程序,修改錯誤,然後再用tar命令生成一個正確的源程序包,覆蓋掉原包即可。這樣,RPM再制作時就不會有問題了。
2.--timecheck:設置時間檢查值
該選項的用法是:--timecheck
注:為檢查的時間段,單位是秒,如--timecheck600設置檢查的時間段為600秒,即10分鐘。
設置時間檢查值的目的,在於檢驗打包文件是否是指定時間段內產生的新文件,如果不是,則RPM會產生警告信息,提醒用戶某個文件不是新文件,而是老文件,可能是某種錯誤導致的。這種錯誤,可能是由於makefile(維護文件)或描述文件中的安裝段腳本程序書寫不正確,從而使某個程序不能正確安裝到指定目錄,因而RPM打包時總是引用老的程序文件。如下面的例子:
#rpm-bl--timecheck600lze-6.0-2.spec
Processingfiles:lze
warning:TIMECHECKfailure:/usr/bin/lze
FindingProvides:(using/usr/lib/rpm/find-provides)...
FindingRequires:(using/usr/lib/rpm/find-requires)...
Provides:lze-edit
PreReq:/bin/sh
Requires:/bin/shld-linux.so.2libc.so.6libc.so.6(GLIBC_2.0)libc.so.6(GLIBC_2.1)
#
注:本例中利用RPM檢查文件列表,看哪個文件是在10分鐘以前產生的老文件,結果RPM發出警告信息:“warning:TIMECHECKfailure:/usr/bin/lze”,這說明文件/usr/bin/lze時間檢查出現錯誤,這是個老文件。經查,是makefile的問題,裡面少了一句“cplze/usr/bin”。修正後,再次編譯連接程序,再進行時間檢查就沒有這個問題了。
3.--buildroot:設定建包用根目錄
該選項的用法是:
--buildroot
注:
為用戶指定的建包用的根目錄。
此選項相當於在軟件包描述文件的文件頭加上一行:
Buildroot:
只不過在命令行上設定比較自由罷了。
通過設定建包用根目錄,一般用戶也可以建立那些只有超級用戶(root)才能建立的RPM包了。下面以普通用戶zzz建立LZE軟件包為例,說明一下這種形式的包的建立過程。
1)在用戶zzz的HOME目錄(/usr/zzz)下,建立RPM建包所用的目錄:
$cd/usr/zzz
$mkdir-prpm/{BUILD,RPMS/i386,SOURCES,SPECS,SRPMS}
$
2)拷貝描述文件lze-6.0-2.spec到rpm/SPECS目錄,拷貝源程序包lze-6.0-2.src.tgz到rpm/SOURCES目錄。
$cd/usr/zzz
$cp/root/lze-6.0-2.specrpm/SPECS
$cp/root/lze-6.0-2.src.tgzrpm/SOURCES
$
3)建立.rpmmacros文件,編輯它:
$cd/usr/zzz
$vi.rpmmacros
在此文件中增加一行:
%_topdir/usr/zzz/rpm
用於確定RPM建包用的頂層目錄為/usr/zzz/rpm。
4)轉到描述文件目錄,編輯修改lze-6.0-2.spec安裝段的腳本程序:
$cd/usr/zzz/rpm/SPECS
$vilze-6.0-2.spec
$
用於確定RPM建包用的頂層目錄為/usr/zzz/rpm。
安裝段腳本程序修改為:(原make命令被注釋掉)
%install
echo"安裝腳本程序(install)開始執行"
#makeinstall
mkdir-p$RPM_BUILD_ROOT/usr/bin
mkdir-p$RPM_BUILD_ROOT/etc
mkdir-p$RPM_BUILD_ROOT/usr/doc/lze-6.0
cplzelzeime.wblzeime.py$RPM_BUILD_ROOT/usr/bin
cpinputme.deffunkey.defwbzc.dat$RPM_BUILD_ROOT/etc
cp/usr/doc/lze-6.0/*$RPM_BUILD_ROOT/usr/doc/lze-6.0
注:腳本程序中,使用建包用根目錄的環境變量RPM_BUILD_ROOT,相繼在建包用根目錄下創建若干子目錄(usr/bin,etc,usr/doc/lze-6.0),然後拷貝程序或文件到相應的子目錄中,從而完成完裝。 5)選用--buildroot選項,執行RPM建包命令:
$cd/usr/zzz/rpm/SPECS
$rpm-bb--buildroot/usr/zzz/tmplze-6.0-2.spec
Executing:%prep
+umask022
+cd/usr/zzz/rpm/BUILD
+echo'預處理腳本程序(prep)開始執行'
預處理腳本程序(prep)開始執行
+cd/usr/zzz/rpm/BUILD