定制Linux发行版(2):定制自己的软件包格式

redhat系统的软件包名字一般为.el6.rpm,假设我们要打造一款名为K-UX的操作系统,那我们可以使用mock,编译出.kux.rpm形式的软件包。在阅读本文之前,你可能需要知道rpmbuild和mock的原理及相关使用方法,这些本博客以前都介绍过。本文的实验环境为CentOS 6.4 x86_64。

为什么要使用mock?

mock是Linux平台下编译.src.rpm的工具,它是在rpmbuild上封装了一层,与rpmbuild相比,它的好处是可以自动解决安装过程中产生的各种依赖关系。而rpmbuild不能自动解决这些依赖关系。既然依赖关系解决了,那就可以写个简单的脚本,实现批量编译.src.rpm的任务了。

按理说,如果要大量编译.src.rpm包,应该使用Fedora提供的Koji工具,但因为Koji太过庞大,配置起来极其复杂,因此还是使用更为小巧智能的mock比较方便。

一,使用rpmbuild编译.kux.rpm格式的软件包

首先需要知道一点儿系统基础:
%dist一般表示操作系统平台,如el5、el6,我们要修改的.kux也需要修改此值
%arch一般表示硬件平台,i386、i686、ia64、x86_64等
要build出.kux.rpm格式的软件包,首先需要修改/etc/rpm/macros.dist文件

[[email protected] ~]# rpm -qf /etc/rpm/macros.dist 
centos-release-6-4.el6.centos.10.x86_64  #由该软件包释放

[[email protected] ~]# cat /etc/rpm/macros.dist 
# dist macros.

%rhel 6
%centos 6
%centos_ver 6
%dist .kux    #将这里的el6修改为kux
%el6 1

然后,再通过rpmbuild命令就可以编译出.kux.rpm格式的软件包了
需要注意的是,Redhat系统里的macros.dist由redhat-release-sever-6servere软件包释放,而CentOS系统里的macros.dist由centos-release-6软件包释放;

[[email protected] ~]# rpm -ql centos-release-6
/etc/centos-release
/etc/issue
/etc/issue.net
/etc/pki/rpm-gpg
/etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
/etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-Debug-6
/etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-Security-6
/etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-Testing-6
/etc/redhat-release
/etc/rpm/macros.dist
/etc/system-release
/etc/system-release-cpe
/etc/yum.repos.d/CentOS-Base.repo
/etc/yum.repos.d/CentOS-Debuginfo.repo
/etc/yum.repos.d/CentOS-Media.repo
/etc/yum.repos.d/CentOS-Vault.repo
/usr/share/doc/centos-release-6
/usr/share/doc/centos-release-6/EULA
/usr/share/doc/centos-release-6/GPL
/usr/share/doc/redhat-release

通过如上命令看出,该软件包主要释放一些定制系统的信息。如果要打造自己的定制系统,那么该软件包是肯定要修改的。

二,修改.kux.rpm软件包的信息

使用rpm -qpi命令查看刚才编译出的软件包,好像少了些什么东西

[[email protected] ~]# rpm -qpi ../RPMS/x86_64/shadow-utils-4.1.4.2-13.kux.x86_64.rpm
Name        : shadow-utils                 Relocations: (not relocatable)
Version     : 4.1.4.2                      Vendor: (none)
Release     : 13.kux                       Build Date: Sat 21 Dec 2013 07:15:30 PM CST
Install Date: (not installed)              Build Host: bear
Group       : System Environment/Base      Source RPM: shadow-utils-4.1.4.2-13.kux.src.rpm
Size        : 4870526                      License: BSD and GPLv2+
Signature   : (none)
Packager    : (none)
URL         : http://pkg-shadow.alioth.debian.org/
Summary     : Utilities for managing accounts and shadow password files
Description :
The shadow-utils package includes the necessary programs for
converting UNIX password files to the shadow password format, plus
programs for managing user and group accounts.

仔细一看,原来是Packager及Vendor显示为none。这两个值是在~/.rpmmacros文件中定义(注意是执行rpmbuild用户的家目录里)。所以这里我们需要修改该文件(如果不存在就新建一个)。

[[email protected] ~]# vi ~/.rpmmacros 
%packager	bear <[email protected]>
%vendor     zhukun.net http://www.zhukun.net

然后重新调用rpmbuild编译之,就会发现编译出来的软件包含有Packager及Vendor信息了。

三,使用mock编译.kux.rpm格式的软件包

由于mock并不是真实环境里编译,而是在一个最小化的环境里来实现编译工作的,因此要达到以上两点儿目标,稍显复杂。
(1)mock是利用yum下载基础软件包来构筑一个最小化的系统,所以yum源的centos-release-6软件包必须是自已修改过的(即修改过软件包里的/etc/rpm/macros.dist的值)
(2)mock是在最小化的环境里调用rpmbuild来编译的,要在最小化的环境里写入~/.rpmmacros也是一个问题。
这里我们来一一解决它。

3.1 定制自己的yum源

1,在真实系统里编译出centos-release-6-4.kux.x86_64.rpm (过程请参考前面两步)。第一步修改真实系统里的/etc/rpm/macros.dist文件;第二步修改spec文件,查找macros.dist,把%%dist后面的值改为.kux;第三步是调用rpmbuild命令编译出该软件包;
2,将编译好的centos-release-6-4.kux.x86_64.rpm替换掉yum源上同名的.el6.x86_64.rpm文件;
3,在yum源上调用createrepo命令重新生成repodata信息;

3.2 mock的设置

要修改mock构筑的最小化系统信息,我们只能修改mock的源代码,好在Mock是使用python编写的,不太复杂。

[[email protected] ~]# cd /usr/lib/python2.6/site-packages/mock  #mock的源代码在此目录下
[[email protected] mock]# vi backend.py

找到buildDirSetup函数,添加%packager和%vendor信息,如下所示:

def _buildDirSetup(self):
    # create all dirs as the user who will be dropping things there.
    self.uidManager.becomeUser(self.chrootuid, self.chrootgid)
    try:
        # create dir structure
        for subdir in [self.makeChrootPath(self.builddir, s) for s in ('RPMS', 'SRPMS', 'SOURCES', 'SPECS', 'BUILD', 'BUILDROOT', 'originals')]:
            mock.util.mkdirIfAbsent(subdir)

        # change ownership so we can write to build home dir
        for (dirpath, dirnames, filenames) in os.walk(self.makeChrootPath(self.homedir)):
            for path in dirnames + filenames:
                os.chown(os.path.join(dirpath, path), self.chrootuid, -1)
                os.chmod(os.path.join(dirpath, path), 0755)

        # rpmmacros default
        macrofile_out = self.makeChrootPath(self.homedir, ".rpmmacros")
        rpmmacros = open(macrofile_out, 'w+')
        for key, value in self.macros.items():
            rpmmacros.write( "%s %s\n" % (key, value) )
	#添加如下两行,注意跟上面的for对齐,不要跟上一行的rpmmacros.write()对齐
        rpmmacros.write(r'%packager Inspur <[email protected]>' + '\n')
        rpmmacros.write(r'%vendor Inspur http://www.zhukun.net' + '\n')
        rpmmacros.close()

        finally:
            self.uidManager.restorePrivs()

这样,使用mock编译出的软件包,就会一切正常了。还可以手动编译一个脚本,实现自动编译的工作。

参考资料:CreateRPMBuildEnvironment

发表评论

您的电子邮箱地址不会被公开。