使用rpmbuild制作RPM包

每个 RPM 软件包由三个基本组件组成:
1. 元数据 – 关于软件包的数据:软件包名称、版本、发布、构建程序、日期、依赖关系等。
2. 文件 – 软件包提供的文件存档(包括文件属性)
3. 脚本 – 安装、更新和 / 或删除软件包时,执行这些脚本
当构建 RPM 软件包时,需要指定软件包的元数据,需要提供存档中的文件以及当需要嵌入或卸载软件包时
应运行的脚本。文件在软件包文件中存储为cpio存档。使用rpm2cpio命令可用于将其抽取到当前工作目录,以查看包文件,例如:rpm2cpio package-1.2.3-4.el6.x86_64.rpm | cpio -id

RPM 软件包规则:
若要构建RPM软件包,您需要内部版本规则文件或spec文件。Spec文件是包含关于如何构建可安装的RPM软件包的信息的文本文件。其大致分为五部分:
1. 列出关于软件包的元数据(名称、版本、许可证等)
2. 构建说明,详细说明如何编写和准备软件
3. 脚本小程序,详细说明安装、卸载或升级时要运行的命令
4. 清单,软件包文件列表及其关于软件包安装的权限
5. changelog ,记录对此RPM软件包所做的更改

rpmbuild 步骤:
1. 准备
2. 构建
3. 安装
4. 打包完成的 RPM
5. 清理

试做一个小的RPM包,环境RHEL6.2,留下作为笔记。
一、相关目录
~/rpmbuild/SOURCES/ 存放源码压缩包和补丁文件
~/rpmbuild/BUILD/ 存放源码
~/rpmbuild/SPECS/ 存放spec文件
~/rpmbuild/RPMS/ 最终RPM包
相关命令:rpmbuild
二、准备GPG签名密钥
[kevin@desktop25 SPECS]$ sudo yum install pinentry-gui -y
[kevin@desktop25 work]$ gpg --gen-key
一直往下就行,内容随意,密码自定。后面会提示输入密码,确认密码。确认然密码等待随机数,这时鼠标随意移动生成随机数。我这里yong密码kevin生成密钥:
@查看密钥:
[kevin@desktop25 SPECS]$ gpg --list-key
/home/kevin/.gnupg/pubring.gpg
------------------------------
pub   2048R/8156471D 2012-03-07
uid                  kevin (kevin) <kevin@kevin.org>
sub   2048R/641335E8 2012-03-07
@导出公共密钥:
[kevin@desktop25 SPECS]$ gpg -a -o ~/RPM-GPG-KEY-kevin --export 8156471D
@将以下内容添加到 ~/.rpmmacros 文件(用系统的密钥 ID 替换该八个字符密钥 ID ),因此, RPM 将用您在上面创建的密钥签署软件包。
[kevin@desktop25 SPECS]$ echo '%_gpg_name 8156471D' > ~/.rpmmacros

二、写个小例子:显示当前目录下的文件及目录树(引用linuxsir上一脚本,谢谢作者)
[kevin@desktop25 work]$ vim file_tree
——————————————————————————————
#!/bin/bash

redir ()
{
        #tab是真正的步长计算器
        tab=$tab$singletab
        line=${tab%"$singletab"}"|-------"

        #local比较关键,它规定了count是当前的参数列表值
        local count=$#

        for file in "$@"; do
                thisfile=${thisfile:-$PWD}/$file

                #判断当前文件是否为目录,如果是就开始递归  
                if [ -d "$thisfile" ]; then
                       
                        #如果当前目录是分枝列表的最底层,则需进行特殊处理。
                        if [ $count -eq 1 ]; then
                                echo -e $line$file/
                                #将前一个|符号去掉,看看目录树就知道为什么了。
                                tab=${tab%"$singletab"}"\t"
                                redir $(ls $thisfile)
                        else

                                echo -e $line$file/
                                redir $(ls $thisfile)
                        fi
                       
                else
                        echo -e $line$file
                fi
               
                thisfile=${thisfile%/*}
                let count=count-1      
        done
       
        #这一步比较有意思,因为从递归出来的tab结尾可能是TAB也可能是$singletab,所以分成两步来去掉。
        tab=${tab%"\t"}
        tab=${tab%"|"}
        line=${tab%"$singletab"}"|-------"
}


singletab="|\t"
userinput="$@"
if ls $userinput; then

        for file in ${userinput:-.}; do
                echo $file
                echo '|'
                if [ -d "$file" ]; then
                        cd $file
                        redir $(ls)
                        cd ..
                fi
        done
else
        echo "$userinput is wrong"
fi

——————————————————————————————
[kevin@desktop25 work]$ chmod +x file_tree
[kevin@desktop25 work]$ mkdir file_tree-1.0
[kevin@desktop25 work]$ mv file_tree file_tree-1.0/
[kevin@desktop25 work]$ tar -zcf file_tree-1.0.tar.gz file_tree-1.0/
[kevin@desktop25 work]$ vim file_tree.spec
——————————————————————————————
Name:           file_tree   
Version:        1.0   
Release:        1%{?dist}   
Summary:        list files in current folder.   

Group:          file_tree    (所属团体)
License:        GPL    (协议)
URL:            http://192.168.0.25/testing   
Source0:        %{name}-%{version}.tar.gz    (源包的名字)
BuildRoot:      %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)

BuildRequires:  /bin/rm,/bin/mkdir,/bin/cp    (所需命令)
Requires:       /bin/bash,/bin/date    (所需命令)

%description   
list files in current folder.

%prep
%setup -q


%build (注意这里删除了下面两行 configure 和 make)

%install
rm -rf $RPM_BUILD_ROOT
#make install DESTDIR=$RPM_BUILD_ROOT    (记得注释掉)
mkdir -p $RPM_BUILD_ROOT/usr/local/bin    (创建安装目录)
cp file_tree $RPM_BUILD_ROOT/usr/local/bin    (拷贝文件到目录)


%clean
rm -rf $RPM_BUILD_ROOT


%files
%defattr(-,root,root,-)
#%doc
%attr(0755,root,root)/usr/local/bin/file_tree    (加上脚本的权限)

%changelog    (软件说明)
*Wed Mar 7 2012 kevin<chu345258361@gmail.com>
-Inital RPM
-Added /usr/local/bin/file_tree

——————————————————————————————
[kevin@desktop25 work]$ sudo yum install rpmbuild -y
[kevin@desktop25 work]$ rpmbuild ~    (运行 rpmbuild 命令将创建
RPM 软件包所需的目录结构。)
[kevin@desktop25 work]$ cp file_tree.spec ~/rpmbuild/SPECS/
[kevin@desktop25 work]$ cp file_tree-1.0.tar.gz ~/rpmbuild/SOURCES/
[kevin@desktop25 work]$ cd ~/rpmbuild/SPECS/
[kevin@desktop25 SPECS]$ rpmbuild --sign -ba file_tree.spec
输入密码:未报错,OK。
[kevin@desktop25 SPECS]$ pwd
/home/kevin/rpmbuild/SPECS
[kevin@desktop25 SPECS]$ ls ../RPMS/x86_64/
file_tree-1.0-1.el6.x86_64.rpm
生成rpm包 file_tree-1.0-1.el6.x86_64.rpm 。
通过安装密钥和软件包并运行命令来测试软件包:
[kevin@desktop25 x86_64]$ sudo rpm --import ~/RPM-GPG-KEY-kevin
[kevin@desktop25 x86_64]$ cd ~/rpmbuild/RPMS/x86_64/
[kevin@desktop25 x86_64]$ rpm -ivh file_tree-1.0-1.el6.x86_64.rpm
[kevin@desktop25 x86_64]$ file_tree     (输入命令file_tree显示当前文件)
OK

四、发布RPM软件包
[kevin@desktop25 x86_64]$ sudo yum install createrepo -y
(创建本地源repodata作为软件的仓库)
[kevin@desktop25 x86_64]$ sudo mkdir /var/ftp/pub/testing
[kevin@desktop25 x86_64]$ sudo cp file_tree-1.0-1.el6.x86_64.rpm /var/ftp/pub/testing/
[kevin@desktop25 x86_64]$ sudo createrepo -v /var/ftp/pub/testing/
1/1 - file_tree-1.0-1.el6.x86_64.rpm

Saving Primary metadata
Saving file lists metadata
Saving other metadata

[kevin@desktop25 x86_64]$ sudo cp ~/RPM-GPG-KEY-kevin /var/ftp/pub/testing/
加入yum源:
[yum]
name=yum
baseurl=http://192.168.0.25/pub/testing
enabled=1
gpgkey=http://192.168.0.25/pub/testing/RPM-GPG-KEY-kevin


验证:
[kevin@desktop20 ~]$ sudo yum install file_tree -y
OK,发布成功~