使用rpm-build製作nginx的rpm包

一、RPM包的分類

RPM有五種基本的操作功能:安裝、卸載、升級、查詢和驗證。

linux軟件包分爲兩大類:

(1)二進制類包,包括rpm安裝包(一般分爲i386和x86等幾種)

(2)源碼類包,源碼包和開發包應該歸位此類(.src.rpm)。

有時候爲了方便源碼包的安裝,和我們自己訂製軟件包的需求,我們會把一些源碼包按照我們的需求來做成rpm包,當有了源碼包就可以直接編譯得到二進制安裝包和其他任意包。spec file是製作rpm包最核心的部分,rpm包的製作就是根據spec file來實現的。在製作自定義rpm包的時候最好不要使用管理員進行,因爲管理員權限過大,如果一個命令寫錯了,結果可能是災難性的,而製件一個rpm包普通用戶完全可以實現

二、修改宏及自定義車間位置

在redhat下,rpm包的默認製作路徑在/usr/src/redhat下,這其中包含了6個目錄(要求全部大寫)

Directory     Usage
BUILD 	      源代碼解壓以後放的位置,只需提供BUILD目錄,具體裏面放什麼,不用我們管,所以真正的製作車間是BUILD目錄
RPMS          製作完成後的rpm包存放目錄,爲特定平臺指定子目錄(i386,i686,ppc)
SOURCES       收集的源文件,源材料,補丁文件等存放位置    
SPECS         存放spec文件,作爲製作rpm包的領崗文件,以 rpm名.spec
SRPMS         src格式的rpm包位置 ,既然是src格式的包,就沒有平臺的概念了           
BuiltRoot     假根,使用install臨時安裝到這個目錄,把這個目錄當作根來用的,所以在這個目錄下的目錄文件,纔是真正的目錄文件。當打包完成後,在清理階段,這個目錄將被刪除

但centos並沒有該目錄,因此,我們不得不自定義工作車間,即使在redhat下有該目錄,一般也是自定義到普通用戶的家目錄下的

rpmbuild --showrc 顯示所有的宏,以下劃線開頭,一個下劃線:定義環境的使用情況,二個下劃線:通常定義的是命令,爲什麼要定義宏,因爲不同的系統,命令的存放位置可能不同,所以通過宏的定義找到命令的真正存放位置

查看默認工作車間,所以只要改變了這個宏,我們就可以自定義工作車間了

[root@localhost /]# rpmbuild --showrc | grep topdir
-14: _builddir	%{_topdir}/BUILD
-14: _buildrootdir	%{_topdir}/BUILDROOT
-14: _desktopdir	%{_datadir}/applications
-14: _rpmdir	%{_topdir}/RPMS
-14: _sourcedir	%{_topdir}/SOURCES
-14: _specdir	%{_topdir}/SPECS
-14: _srcrpmdir	%{_topdir}/SRPMS
-14: _topdir	%{getenv:HOME}/rpmbuild

三、rpm包製作原理圖

wKiom1RtybbxDoijAARlofRyCW4338.jpg

四、製作rpm包

1、安裝rpm-build

# yum -y install rpm-build

2、增加普通用戶並修改工作車間目錄

# useradd hero
# su - hero
$ vim ~/.rpmmacros
  %_topdir        /home/hero/rpmbuild
# mkdir -pv ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} 
# rpmbuild --showrc | grep _topdir    #會發現,工作車間已然改變:_topdir	/home/hero/rpmbuild

3、收集源碼文件

(1)文件列表

[root@localhost SOURCES]# pwd
/home/hero/rpmbuild/SOURCES
[root@localhost SOURCES]# ls
fastcgi_params  init.nginx  nginx-1.7.7.tar.gz  nginx.conf

(2)nginx-1.7.7.tar.gz 源碼包

$ cp /opt/src/nginx-1.7.7.tar.gz /home/hero/rpmbuild/SOURCES/

(3)init.nginx 腳本文件

#!/bin/sh
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig:   - 85 15
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
## config:      /etc/nginx/nginx.conf
# config:      /usr/local/nginx/conf/nginx.conf
# config:      /etc/sysconfig/nginx
## pidfile:     /var/run/nginx/nginx.pid
# pidfile:     /usr/local/nginx/logs/nginx.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
nginx="/usr/local/nginx/sbin/nginx"
prog=$(basename $nginx)
#NGINX_CONF_FILE="/etc/nginx/nginx.conf"
NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"
[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx
lockfile=/var/lock/subsys/nginx
make_dirs() {
   # make required directories
   user=`nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -`
   options=`$nginx -V 2>&1 | grep 'configure arguments:'`
   for opt in $options; do
       if [ `echo $opt | grep '.*-temp-path'` ]; then
           value=`echo $opt | cut -d "=" -f 2`
           if [ ! -d "$value" ]; then
               # echo "creating" $value
               mkdir -p $value && chown -R $user $value
           fi
       fi
   done
}
start() {
    [ -x $nginx ] || exit 5
    [ -f $NGINX_CONF_FILE ] || exit 6
    make_dirs
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}
stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}
restart() {
    configtest || return $?
    stop
    sleep 1
    start
}
reload() {
    configtest || return $?
    echo -n $"Reloading $prog: "
    killproc $nginx -HUP
    RETVAL=$?
    echo
}
force_reload() {
    restart
}
configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}
rh_status() {
    status $prog
}
rh_status_q() {
    rh_status >/dev/null 2>&1
}
case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
        exit 2
esac

(4)fastcgi_params 參數

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;
fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

4、在 SPECS 目錄下創建 nginx.spec

$ cd rpmbuild/SPECS/
$ vim nginx.spec     #此時,裏面就是一個模板,直接填就可以了

### 1.The introduction section 

Name: nginx          # 軟件包名稱
Version: 1.7.7       # 版本號,(不能使用-)
Release: 3%{?dist}   # release號,對應下面的changelog,如 nginx-1.7.7-3.el6.x86_64.rpm
Summary: nginx-1.7.7.tar.gz to nginx-1.7.7.rpm   # 簡要描述信息,最好不要超過50個字符,如要詳述,使用下面的%description
Group: Applications/Archiving      # 要全用這裏面的一個組:less /usr/share/doc/rpm-version/GROUPS
License: GPLv2                     # 一定帶上(最好是對方源碼包的License)BSD,GPL,GPLv2
URL: http://nmshuishui.blog.51cto.com/
Packager: nmshuishui <[email protected]>
Vendor: nmshuishui
Source0: %{name}-%{version}.tar.gz     # source主要是引用一下自己定義好的腳本,配置文件之類的內容。
Source1: init.nginx                    # nginx在主配置文件裏面做了很多優化,包括cpu搶佔,各種緩存策略,tcp,進程數等。
Source2: nginx.conf                    # 每增加一個 Source ,都需要在 %install 段和 %files 段做相應配置,如果是啓動腳本的話,最好在腳本段配置一下
Source3: fastcgi_params
BuildRoot: %_topdir/BUILDROOT 

BuildRequires: gcc
Requires: openssl,openssl-devel,pcre-devel,pcre  # 定義nginx依賴的包,需要yum安裝

%description              # 軟件包詳述
Custom a rpm by yourself!Build nginx-1.7.7.tar.gz to nginx-1.7.7.rpm

###  2.The Prep section 準備階段,主要就是把源碼包解壓到build目錄下,設置一下環境變量,並cd進去

%prep 
%setup -q    # 這個宏的作用靜默模式解壓並cd 

###  3.The Build Section 編譯製作階段,這一節主要用於編譯源碼

%build

%configure          #在 RMP 創建時候, 由於 nginx 不按照常規定義, 不可以定義 %{_prefix} 之類參數, 也不可以使用 %configure 這個參數進行 rpm 編譯  
                    #一旦定義該參數, 會導致編譯自動增加下面參數, 導致報錯
                    # + ./configure --build=x86_64-redhat-linux-gnu --host=x86_64-redhat-linux-gnu --target=x86_64-redhat-linux-gnu --program-prefix=
                    #因此,這裏需要 ./configure,且需把%configure刪掉
                    #而且這裏需要安裝 pcre-devel包,如果沒有的話,會提示關於pcre的錯誤,直接安裝此包就可以了
./configure \
--prefix=/usr/local/nginx \
--user=www \
--group=www \
--with-http_ssl_module \
--with-http_flv_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/tmp/nginx/client/ \
--http-proxy-temp-path=/var/tmp/nginx/proxy/ \
--http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \
--http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \
--http-scgi-temp-path=/var/tmp/nginx/scgi \
--with-pcre
make %{?_smp_mflags}            # make後面的意思是:如果就多處理器的話make時並行編譯 

###  4.Install section  這一節主要用於完成實際安裝軟件必須執行的命令,可包含4種類型腳本

%install
rm -rf %{buildroot}
make install DESTDIR=%{buildroot}
%{__install} -p -D -m 0755 %{SOURCE1} %{buildroot}/etc/rc.d/init.d/nginx
%{__install} -p -D %{SOURCE2} %{buildroot}/usr/local/nginx/conf/nginx.conf
%{__install} -p -D %{SOURCE3} %{buildroot}/usr/local/nginx/conf/fastcgi_params

%pre
if [ $1 == 1 ];then                                                         # $1有3個值,代表動作,安裝類型,處理類型
        /usr/sbin/useradd -r www -s /sbin/nologin 2> /dev/null              # 1:表示安裝
fi                                                                          # 2:表示升級      
                                                                            # 0:表示卸載
%post
if [ $1 == 1 ];then
        /sbin/chkconfig --add %{name}
        /sbin/chkconfig %{name} on
        echo '# Add  #下面主要是內核參數的優化,包括tcp的快速釋放和重利用等。   
net.ipv4.tcp_max_syn_backlog = 65536
net.core.netdev_max_backlog =  32768
net.core.somaxconn = 32768
 
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
 
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
 
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
 
net.ipv4.tcp_mem = 94500000 915000000927000000
net.ipv4.tcp_max_orphans = 3276800
 
#net.ipv4.tcp_fin_timeout = 30
#net.ipv4.tcp_keepalive_time = 120
net.ipv4.ip_local_port_range = 1024  65535' >> /etc/sysctl.conf
sysctl -p 2>&1 /dev/null
fi

%preun
if [ $1 == 0 ];then
        /usr/sbin/userdel -r www 2> /dev/null
        /etc/init.d/nginx stop > /dev/null 2>&1
fi
%postun

###  5.clean section 清理段,clean的主要作用就是刪除BUILD

%clean
rm -rf %{buildroot}

###  6.file section 文件列表段,這個階段是把前面已經編譯好的內容要打包了,其中exclude是指要排除什麼不打包進來。

%files              
%defattr(-,root,root,0755)
/usr/local/nginx/
%attr(0755,root,root) /etc/rc.d/init.d/nginx
%config(noreplace) /usr/local/nginx/conf/nginx.conf
%config(noreplace) /usr/local/nginx/conf/fastcgi_params

###  7.chagelog section  日誌改變段, 這一段主要描述軟件的開發記錄

%changelog
*  Thu Wed 26 2014 nmshuishui <[email protected]> - 1.7.7-3
- Initial version

5、製作rpm包

rpmbuild -bp nginx.spec 製作到%prep段
rpmbuild -bc nginx.spec 製作到%build段
rpmbuild -bi nginx.spec 執行 spec 文件的 "%install" 階段 (在執行了 %prep 和 %build 階段之後)。這通常等價於執行了一次 "make install"
rpmbuild -bb nginx.spec 製作二進制包
rpmbuild -ba nginx.spec 表示既製作二進制包又製作src格式包

五、rpm包的簽名

1、查詢軟件包信息

[root@localhost ~]# rpm -qi nginx
Name        : nginx                        Relocations: (not relocatable)
Version     : 1.7.7                             Vendor: nmshuishui
Release     : 3.el6                         Build Date: Wed 26 Nov 2014 06:39:00 PM CST
Install Date: Wed 26 Nov 2014 06:42:19 PM CST      Build Host: localhost
Group       : Applications/Archiving        Source RPM: nginx-1.7.7-3.el6.src.rpm
Size        : 793593                           License: GPLv2
Signature   : (none)    # rpm包未簽名狀態
Packager    : nmshuishui <[email protected]>
URL         : http://nmshuishui.blog.51cto.com/
Summary     : nginx-1.7.7.tar.gz to nginx-1.7.7.rpm
Description :
Custom a rpm by yourself!Build nginx-1.7.7.tar.gz to nginx-1.7.7.rpm

2、使用gpg方式生成簽名密鑰

[root@localhost ~]# gpg --gen-key
Your selection?1<Enter>  #默認即可
What keysize do you want? (2048) 1024<Enter>  #選擇密鑰長度
Key is valid for? (0) 1y<Enter>  #有效期
Is this correct? (y/N) y<Enter>  #確認
Real name: nmshuishui<Enter>  #密鑰名稱
Email address: [email protected]<Enter>  #郵件
Comment: GPG-RPM-KEY<Enter>  #備註
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O<ENTER> #okay確認
Enter passphrase  OK <Enter>  #按Enter輸入密碼                    
<Take this one anyway> <Enter> #確認使用此密碼
#####
在生成密鑰的時候,會報這麼一個信息:can't connect to `/root/.gnupg/S.gpg-agent': No such file or directory,可以不用理會它。
接下來就是一些隨機數的說明了:We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
就狂敲鍵盤和移動鼠標吧,也可以鏈接一個僞隨機數(不過不安全),接下來的活兒就是等了
生成密鑰後會是這樣的:
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
pub   2048R/DF63EDFB 2014-11-26
      Key fingerprint = 338D 476F 29C9 E2D6 6604  1D96 6F73 1E81 DF63 EDFB
uid                  nmshuishui (gen-key) <[email protected]>
sub   2048R/263FB359 2014-11-26

3、查看生成的密鑰

[root@localhost ~]# gpg --list-keys
/root/.gnupg/pubring.gpg
------------------------
pub   2048R/DF63EDFB 2014-11-26
uid                  nmshuishui (gen-key) <[email protected]>
sub   2048R/263FB359 2014-11-26

4、導出公鑰以供驗證

[root@localhost ~]# gpg --export -a "nmshuishui" > RPM-GPG-KEY-nmshuishui

5、在~/.rpmmacros宏中定義加密密鑰

[root@localhost ~]# vim ~/.rpmmacros
%_gpg_name nmshuishui

6、爲rpm包簽名

[root@localhost ~]# rpm --addsign /home/hero/rpmbuild/RPMS/x86_64/nginx-1.7.7-3.el6.x86_64.rpm 
Enter pass phrase: 
Pass phrase is good.
/home/hero/rpmbuild/RPMS/x86_64/nginx-1.7.7-3.el6.x86_64.rpm:

7、將公鑰導入rpm包

[root@localhost ~]# rpm --import RPM-GPG-KEY-nmshuishui

8、驗證

[root@localhost ~]# rpm --checksig /home/hero/rpmbuild/RPMS/x86_64/nginx-1.7.7-3.el6.x86_64.rpm
/home/hero/rpmbuild/RPMS/x86_64/nginx-1.7.7-3.el6.x86_64.rpm: rsa sha1 (md5) pgp md5 OK

9、重新安裝nginx,驗證安裝包的簽名信息

[root@localhost ~]# rpm -ivh /home/hero/rpmbuild/RPMS/x86_64/nginx-1.7.7-3.el6.x86_64.rpm 
Preparing...                ########################################### [100%]
   1:nginx                  ########################################### [100%]
[root@localhost ~]# 
[root@localhost ~]# rpm -qi nginx
Name        : nginx                        Relocations: (not relocatable)
Version     : 1.7.7                             Vendor: nmshuishui
Release     : 3.el6                         Build Date: Wed 26 Nov 2014 06:39:00 PM CST
Install Date: Thu 27 Nov 2014 10:58:44 AM CST      Build Host: localhost
Group       : Applications/Archiving        Source RPM: nginx-1.7.7-3.el6.src.rpm
Size        : 793593                           License: GPLv2
Signature   : RSA/SHA1, Thu 27 Nov 2014 10:40:02 AM CST, Key ID 6f731e81df63edfb   # 與 1 比起來,多了簽名信息
Packager    : nmshuishui <[email protected]>
URL         : http://nmshuishui.blog.51cto.com/
Summary     : nginx-1.7.7.tar.gz to nginx-1.7.7.rpm
Description :
Custom a rpm by yourself!Build nginx-1.7.7.tar.gz to nginx-1.7.7.rpm

到這裏,一個完整的 rpm 包就製作完成了!



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章