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文件
[root@os2 ~]# rpm -qf /etc/rpm/macros.dist
centos-release-6-4.el6.centos.10.x86_64 #由该软件包释放
[root@os2 ~]# 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软件包释放;
[root@os2 ~]# 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命令查看刚才编译出的软件包,好像少了些什么东西
[root@bear ~]# 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用户的家目录里)。所以这里我们需要修改该文件(如果不存在就新建一个)。
[root@bear ~]# 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编写的,不太复杂。
[root@os2 ~]# cd /usr/lib/python2.6/site-packages/mock #mock的源代码在此目录下
[root@mock 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编译出的软件包,就会一切正常了。还可以手动编译一个脚本,实现自动编译的工作。