首頁 > 軟體

如何製作RPM包

2020-06-16 17:34:05

安裝製作rpm工具rpmbuild

yum install -y rpm-build

建立使用者

注意: 建立rpm包一定不要使用root使用者,因為root使用者許可權比較大,如果指令碼編寫錯誤的話,可能會導致破壞系統檔案

useradd sysadmin   # 建立普通使用者sysadmin,使用者可隨意
passwd sysadmin  # 給普通使用者設定密碼

建立製作PRM所需的工作目錄

手動建立工作目錄

mkdir -p ~/rpmbuild{BUILD,RPMS,S{OURCE,PEC,RPM}S}

安裝rpmdevtools輔助工具包來自動生成rpmbuild目錄

yum install -y rpmdevtools
rpmdev-setuptree  # 執行此命令來自動生成

目錄詳解

目錄說明macros宏名
BUILD 編譯rpm包的臨時目錄 %_builddir
RPMS 存放由rpmbuild最終製作好的二進位制包 %_rpmdir
SOURCES 所有原始碼和修補程式檔案的存放目錄 %_sourcedir
SPECS 存放SPEC檔案的目錄(重要) %_specdir
SPRMS 最終生成的二進位制原始碼包所在目錄 %_srcrpmdir

注意: 關於rpmbuild預設工作路徑的確定,通常由在/usr/lib/rpm/macros這個檔案裡的一個叫做%_topdir的宏變數來定義,你也可以使用rpmbuild –showrc | grep _topdir 來進行檢視。如果想更改這個目錄名,rpm官方並不推薦直接更改這個目錄,而是在使用者家目錄下建立一個名為.rpmmacros的隱藏檔案(注意前面的點不能少,這是Linux下隱藏檔案的常識),然後在裡面重新定義%_topdir,指向一個新的目錄名。這樣就可以滿足某些“高階”使用者的差異化需求了。通常情況下.rpmmacros檔案裡一般只有一行內容 %_topdir $HOME/newfile

準備要製作的原始碼包和所需的一些額外檔案

例如:修補程式包,服務所需的組態檔以及service管理啟動指令碼等,都放置SOURCES目錄下(獲取nginx原始碼包)

cd ~/rpmbuild/SOURCES
wget http://nginx.org/download/nginx-1.7.7.tar.gz  # 獲取nginx原始碼包
ls  # 檢視當前目錄下的檔案
init.nginx  nginx-1.7.7.tar.gz  nginx.conf

nginx指令碼檔案如下

vim init.nginx  # 編寫啟動服務指令碼,讓其可以使用service和chkconfig來管理
#!/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

進入SPECS目錄

建立nginx.spec檔案

cd ~/rpmbuild/SPECS
rpmdev-newspec nginx.spec  # 可以使用rpmdev-newspec工具來生成,也可以手動vim編寫.

nginx.spec檔案內容如下:

Name: nginx          # 軟體包名稱
Version: 1.7.7        # 版本號,(不能使用-)
Release: 1%{?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://nginx.org/
Packager:  CentOS   # 包提供者
Vendor: centos
Source0: %{name}-%{version}.tar.gz   # source主要是參照一下自己定義好的指令碼,組態檔之類的內容。
Source1: init.nginx    # nginx在主組態檔裡面做了很多優化,包括cpu搶佔,各種快取策略,tcp,進程數等。
Source2: nginx.conf    # 每增加一個Source ,都需要在 %install 段和 %files 段做相應設定,如果是啟動指令碼的話,最好在指令碼段設定一下
BuildRoot: %_topdir/BUILDROOT

BuildRequires: gcc  # 編譯程式碼需要的軟體。這個只影響編譯命令,不影響打包後的rpm包的依賴關係。
Requires: openssl,openssl-devel,pcre-devel,pcre  # 定義nginxrpm安裝時依賴的包,需要提前進行yum手動安裝

%description   # 軟體包的描述,可多行編寫,段中間空行隔開
Custom a rpm by yourself!Build nginx-1.7.7.tar.gz to nginx-1.7.7.rpm

%prep    # 準備階段,主要就是把原始碼包解壓到build目錄下,設定一下環境變數,並cd進去  
%setup -q    # 這個宏的作用靜默模式解壓並cd,並不需要我們手動cd,setup會自動完成初始的工作


%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=nginx 
--group=nginx 
--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時並行編譯 


%install # 此區域主要用來完成實際軟體安裝必須執行的命令,其中可包含4種型別的指令碼
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

%pre  # 安裝前執行的指令碼動作
if [ $1 == 1 ];then                            # $1有3個值,代表動作,安裝型別,處理型別
     /usr/sbin/useradd -r nginx -s /sbin/nologin 2> /dev/null # 1:表示安裝
fi                                                            # 2:表示升級      
                                                              # 0:表示解除安裝
%post # rpm安裝後要執行的指令碼動作
if [ $1 == 1 ];then
        /sbin/chkconfig --add %{name}
        /sbin/chkconfig %{name} on
        echo '   
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   #此檔案中主要是在安裝後做核心引數的優化,包括tcp的快速釋放和重利用等。
fi

%preun  # rpm解除安裝前執行的指令碼動作,可以在下面編寫
if [ $1 == 0 ];then
        /usr/sbin/userdel -r nginx 2> /dev/null
        /etc/init.d/nginx stop > /dev/null 2>&1
fi

%postun # rpm解除安裝後執行的指令碼


%clean  # 清理段,主要用於完成編譯安裝後的清理BUILDROOT和BUILD動作
rm -rf %{buildroot}  

%files  # 檔案列表段,這個階段主要是把前面已經編譯好的內容打包,啟動包括打包那些檔案,其中exlude是指要排除那些包不打包進來.         
%defattr(-,root,root,0755)  # defattr全域性宏,指定下面打包所有檔案的屬主,屬組,許可權
/usr/local/nginx/  # 表示包含此目錄下的所有檔案
%attr(0755,root,root) /etc/rc.d/init.d/nginx  # 此宏是定義單個檔案的許可權
%config(noreplace) /usr/local/nginx/conf/nginx.conf  # 指定為組態檔,noreplace表示是否替換如果之前有的此檔案的話


%changelog   # 紀錄檔改變段,主要用來描述每一次修改做個那寫動作
 *  Thu Sep 2 2016 centos <admin@centos.com> - 1.7.7-1
 * Initial version

總結:總的概括一下,rpmbuild做的事情是以臨時目錄作為虛擬的系統根目錄,然後build,install(需要制定引數,安裝到臨時虛擬根目錄下),然後打包 file塊中制定的目錄結構。注意: %install部分使用的是絕對路徑,而%file部分使用則是相對路徑,雖然其描述的是同一個地方.

下面總結了在您執行 rpmbuid -ba nginx.spec 時,RPMBUILD 都做些什麼:

  • 讀取並解析 nginx.spec 檔案
  • 執行 %prep 部分來將原始碼解包到一個臨時目錄,並應用所有的修補程式程式。
  • 執行%build 部分來編譯程式碼。
  • 執行 %install 部分將程式碼安裝到構建機器的目錄中。
  • 讀取 %files部分的檔案列表,收集檔案並建立二進位制和源 RPM 檔案。
  • 執行 %clean 部分來除去臨時構建目錄。

執行流程圖:


執行打包

注意:在製作RPM包之前你還需要安裝必要的build時所需要工具以及編譯是所依賴的包),此步驟完成後會在RPMS下存在剛才所製作好的RPM包

rpmbuild -bb nginx.spec
rpmbuild 命令選項執行的動作
-bp nginx.spec 製作到%prep段
-bc nginx.spec 製作到%build段
-bi nginx.spec 執行 spec 檔案的 “%install” 階段 (在執行了 %prep 和 %build 階段之後)。這通常等價於執行了一次 “make install”
-bb nginx.spec 製作二進位制包(在執行了 %prep 和 %build 階段之後)
-bs nginx.spec 僅製作原始碼包
-bl nginx.spec 從spec檔案宏擴充套件%files段,檢查並且驗證每個檔案是否存在
-ba nginx.spec 表示既製作二進位制包又製作src格式包(在執行了 %prep 和 %build 階段之後)

END

到此一個ngnix的RPM包就製作好了,這裡面最主要的還是編寫spec檔案,所以我們要想有更多的思路取編寫spec檔案,建議大家取網上搜一些src.rpm包來看看別人的spec檔案是如何進行編寫的,那麼時間長了,我們基本就有一些思路取寫spec檔案了。

本文永久更新連結地址http://www.linuxidc.com/Linux/2016-09/134955.htm


IT145.com E-mail:sddin#qq.com