1. 程式人生 > >SPEC指令碼及RPM打包

SPEC指令碼及RPM打包

1. Makefile示例

all:	dist

.PHONY:	clean

clean:	distclean

dep:	
	
dist:	distclean dep
	sh package/package.sh
	rpmbuild -bb package/confmanage.spec
	cp /usr/src/redhat/RPMS/i386/confmanage*.i386.rpm dist
	rm /usr/src/redhat/RPMS/i386/confmanage*.i386.rpm
	md5sum dist/*.rpm > dist/checksum.txt

distclean:	
	rm -f dist/*.rpm dist/*.txt


2. package/package.sh

#!/bin/sh

PackageDir="/tmp/BUILD/confmanage"
InstallDir="${PackageDir}/usr/local/confmanage"

#建立打包目錄
rm -fr $PackageDir >/dev/null 2>&1
mkdir -m 755 -p $InstallDir

#拷貝需要打包的檔案到打包目錄
cp -r configs $InstallDir
cp -r html $InstallDir
cp -r scripts $InstallDir

#打包前刪除CVS工程檔案
find $InstallDir -type d -name CVS -exec rm -fr {} \+ >/dev/null 2>&1



3. package/confmanage.spec

Summary: 3G Configuration Manage
Name: confmanage
Version: 1.0.3
Release: 1
Vendor: Zed-3, Inc.
License: Zed-3, Inc 2013
Group: Applications/ASG
BuildRoot: /tmp/BUILD/confmanage
%description
This package contains 3G Configuration Manage.

%post

if [ "$1" = "1" ]; then
# Run %post of new package during a new install
	# add user to sudoers
    if ! grep -q 'apache ALL= NOPASSWD' /etc/sudoers
    then
        echo "apache ALL= NOPASSWD: /usr/local/confmanage/scripts/" >>/etc/sudoers
    elif ! cat /etc/sudoers | grep 'apache ALL= NOPASSWD' | grep -q '/usr/local/confmanage/scripts'
	then 
		sed -i 's/^apache ALL= NOPASSWD.*$/&\,\/usr\/local\/confmanage\/scripts\//' /etc/sudoers
	fi
	
   #config apache
    sed -i 's/#Include conf\/extra\/httpd-vhosts.conf/Include conf\/extra\/httpd-vhosts.conf/' /usr/local/httpd/conf/httpd.conf
    if [ ! -e "/usr/local/httpd/conf/extra/httpd-vhosts.conf.bak" ]; then
        cp /usr/local/httpd/conf/extra/httpd-vhosts.conf /usr/local/httpd/conf/extra/httpd-vhosts.conf.bak
    fi
    cp /usr/local/confmanage/configs/cm.conf /usr/local/httpd/conf/extra/httpd-vhosts.conf
    service httpd restart >/dev/null 2>&1
	
	chmod +x -R /usr/local/confmanage/scripts


elif [ "$1" = "2" ]; then
   # during upgrade
	# add user to sudoers
    if ! grep -q 'apache ALL= NOPASSWD' /etc/sudoers
    then
        echo "apache ALL= NOPASSWD: /usr/local/confmanage/scripts/" >>/etc/sudoers
    elif ! cat /etc/sudoers | grep 'apache ALL= NOPASSWD' | grep -q '/usr/local/confmanage/scripts'
	then 
		sed -i 's/^apache ALL= NOPASSWD.*$/&\,\/usr\/local\/confmanage\/scripts\//' /etc/sudoers
	fi
	
   #config apache
    sed -i 's/#Include conf\/extra\/httpd-vhosts.conf/Include conf\/extra\/httpd-vhosts.conf/' /usr/local/httpd/conf/httpd.conf
    if [ ! -e "/usr/local/httpd/conf/extra/httpd-vhosts.conf.bak" ]; then
        cp /usr/local/httpd/conf/extra/httpd-vhosts.conf /usr/local/httpd/conf/extra/httpd-vhosts.conf.bak
    fi
    cp /usr/local/confmanage/configs/cm.conf /usr/local/httpd/conf/extra/httpd-vhosts.conf
    service httpd restart >/dev/null 2>&1
	
	chmod +x -R /usr/local/confmanage/scripts


else
   # Invalid $1 value, neither install nor upgrade, abort!
   exit 1
fi


%postun

if [ "$1" = "0" ]; then
# Run %postun of old package during an erase
	#delete user to sudoers
	sed -i '/^apache ALL= NOPASSWD: \/usr\/local\/confmanage\/scripts\/$/d' /etc/sudoers
	sed -i 's/\,\/usr\/local\/confmanage\/scripts\///' /etc/sudoers
	
	#config apache
    sed -i 's/Include conf\/extra\/httpd-vhosts.conf/#Include conf\/extra\/httpd-vhosts.conf/' /usr/local/httpd/conf/httpd.conf
	if [ -e "/usr/local/httpd/conf/extra/httpd-vhosts.conf.bak" ]; then
		mv /usr/local/httpd/conf/extra/httpd-vhosts.conf.bak /usr/local/httpd/conf/extra/httpd-vhosts.conf
	fi
    service httpd restart >/dev/null 2>&1
    
elif [ "$1" = "1" ]; then
   # during upgrade
   :
else
   # Invalid $1 value, neither install nor upgrade, abort!
   exit 1
fi

%files
%defattr (-,root,root)
/usr/local/confmanage/

 4. apache配置

Listen 8000

NameVirtualHost *:8000

<VirtualHost *:8000> 
    DocumentRoot "/usr/local/confmanage/html"

    <Directory />                 
        Options FollowSymLinks                 
        AllowOverride None         
    </Directory>         

    <Directory /usr/local/confmanage/html>                 
        Options Indexes FollowSymLinks MultiViews                 
        AllowOverride All                 
        Order allow,deny                 
        allow from all         
    </Directory>

    ServerName www.example.com:8000
    ServerAdmin [email protected]
    ErrorLog logs/cm.log
    CustomLog logs/cm.log common

    <FilesMatch \.php$>
        SetHandler application/x-httpd-php
    </FilesMatch>
</VirtualHost>

--------------------------------------------------------------------------------------------------------------------------
 升級RPM過程調研[轉載]

當在使用者機器上安裝或解除安裝程式時,能夠執行命令將是很有用的。例如,可能需要編輯一個系統配置檔案以啟用新的服務,或者需要定義一個新使用者以擁有正在安裝的程式的所有權。

安裝和解除安裝指令碼的工作原理看起來很簡單,但它們工作原理中的一些意外可能會引起大問題。這裡是一些基本資訊,可以將下列四節中的任意一個新增到.spec 檔案,它列出了在包安裝期間各個點上執行的shell 指令碼:

%pre 在安裝包之前執行

%post 在安裝包之後執行

%preun 在解除安裝包之前執行

%postun 在解除安裝包之後執行

尤其要注意%install與這些節之間的差異。構建RPM 時,%install 在開發機器上執行;它應該將產品安裝在開發機器上或安裝到一個構建根目錄中。另一方面,這些節指定當使用者正在安裝或解除安裝RPM包時將在使用者的機器上執行什麼。

一種好的技術是使用%pre指令碼來檢查安裝前提條件,它們比RPM可以直接支援的更復雜。 如果不符合前提條件,那麼指令碼以非零狀態退出,而且 RPM 不會繼續安裝。另外請注意,我們必須小心地使用解除安裝指令碼來撤銷安裝指令碼。

然而實際上沒有那麼簡單:升級使每件事情都變得複雜,現在,讓我們著手升級。如果使用者只安裝和刪除自己的包,那麼前面的指令將正常工作;但在升級期間,它們會完全失效。以下是 RPM 如何執行升級:

執行新包的 %pre

安裝新檔案

執行新包的 %post

執行舊包的 %preun

刪除新檔案未覆蓋的所有舊檔案

執行舊包的 %postun

如果我們使用5.3.2系列中現有SPEC檔案中的指令碼來升級,那麼RPM最後將執行 %postun 指令碼,它將除去我們在安裝指令碼中所做的所有工作。

rpm為了解決此問題,在其英文文件中提到了可以向指令碼來傳遞一個引數$1,這個引數傳遞的過程是隱藏的,你只需在%pre,%post,%preun,%postun中使用$1即可($1在shell中就是第一個引數的意思)。這個引數的含義是在執行完此次操作後系統中此軟體包的剩餘數量是多少,就目前我的理解應該只有0,1,2三種可能。

1.在執行rpm –ivh的安裝過程中,如果有同類包存在,則會報錯提示無法安裝,存在相同的檔案。如果沒有同類包存在則會執行安裝動作,過程如下:

執行新包的%pre $1=1

安裝新檔案

執行新包的%post $1=1

2.在執行rpm –U的升級過程中,如果沒有同類低階包存在,則過程和傳遞的引數與安裝時完全相同,如果有同類低階包存在則會執行升級操作,過程如下:

執行新包的%pre $1=2

安裝新檔案

執行新包的%post $1=2

執行舊包的%preun $1=1

刪除新檔案未覆蓋的任何舊檔案

執行舊包的%postun $1=1

3.在執行rpm –e的刪除過程如下:

執行舊包的%preun $1=0

刪除檔案

執行舊包的%postun $1=0


因此我們可以用傳遞的引數來判斷rpm究竟在進行什麼工作,來在指令碼內部通過$1進行判斷來決定進行什麼動作。例如在引數為0的時候才真的執行解除安裝所要進行的動作。


另外,在升級的時候,RPM還有一項重要的工作要做,這就是妥善處理配置檔案(CONFIG FILE)。若直接採用安裝方式,則使用者已配置好的配置檔案就會被覆蓋,不符合使用者要求。

RPM對某個配置檔案,通過比較三種不同的MD5檢查和(checksum)來決定如何處理它。這三種不同的MD5檢查和是:

1. 原檢查和。它是舊版本軟體包安裝時配置檔案的MD5檢查和。

2. 當前檢查和。它是升級時舊版本配置檔案的MD5檢查和。

3. 新檢查和。它是新版本軟體包中配置檔案的MD5檢查和。

RPM針對以下幾種情況分別處理:

1. 當原檢查和=X,當前檢查和=X,新檢查和=X時:

這表明配置檔案未曾修改過。此時,RPM會將新的配置檔案覆蓋掉原檔案,而不是對原檔案不作處理,原因在於: 雖然檔名和檔案內容都沒有變化,但檔案別的方面的屬性(如檔案的屬主,屬組,許可權等)卻可能改變,所以有必要覆蓋一下。

2. 當原檢查和=X,當前檢查和=X,新檢查和=Y時:
這表明原配置檔案沒有改動過,但是它與新軟體包中的配置檔案卻有所不同。這種情況下,RPM將用新檔案覆蓋掉舊檔案,並且舊檔案不作儲存(因為它不曾改動過,沒有必要儲存)。

3. 當原檢查和=X,當前檢查和=Y,新檢查和=X時:

這表明新檔案與舊檔案內容相同,但當前檔案已經作過修改,這些修改對於新版本來說應該是合法的,可以使用的。因此,RPM對當前檔案予以保留。

4. 當原檢查和=X,當前檢查和=Y,新檢查和=Y時:

這表明原檔案經過修改,現在已與新檔案相同,這或許是使用者用來修補安全上的漏洞,新版本也作了同樣的修改。這種情況下,RPM將新檔案覆蓋當前檔案,避免檔案屬性方面的不同。

5. 當原檢查和=X,當前檢查和=Y,新檢查和=Z時:

這表明使用者已修改了原檔案,並且當前內容與新檔案內容不同。這種情況下,RPM無法保證新版本軟體能正常使用當前的配置檔案,所以採用了一個比較明智的辦 法,既能保護使用者的配置資料,又能保證新版本軟體正常。這種作法就是將當前檔案換名儲存(給原檔名加個.rpmsave的字尾,如原檔名為ABC,則 換名後為ABC.rpmsave),同時安裝新檔案,並給出警告資訊。

6. 當沒有原檢查和時:

此種情況下,當前檢查和與新檢查和已無關緊要,這表明沒有安裝過此配置檔案。因為沒有安裝過此配置檔案,所以RPM無法判斷當前檔案是否被使用者修改過。這種情況下,RPM會將當前檔案換名儲存(原檔名字尾不是加個.rpmsave,而是.rpmorig),同時安裝新檔案,並給出警告資訊。


因此在%files中可以用%config欄位將配置檔案標識出來,這樣在升級的過程中配置檔案將被按照上面所描述的方法處理。

%config 檔案路徑的形式來新增。