如何创建Debian二进制包
1 简介
我们采用这样的方法所创建的文档的用途只是安装在我们自己的系统上,而不是将他们提交到Debian的官方版本中。如果我们要进行官方的开发,我们就需要参考Debian New Maintainers' Guide。
通常Debian的软件包可以得到一个适当的源码包,在这个源码包中包含有在创建Debian的二进制包时自动处理所调用步骤的debian/rules文件。在这里我们只是简单的显示一下如何将一个简单的Shell脚本或是二进制可执行文件打包到一个简单的二进制包中。
在这里我们假定我们知道了如何使用tar,man等命令以及知道.tar.gz文件以及Debian是什么,但是我们却假定我们并没有接触过任何类似于ar或是dpkg的程序。
1.1 Web上的资源
The Debian Reference提供了Debian各种详细的信息。
创建我们自己的Debian软件包的官方文档是Debian New Maintainers' Guide。
2 开始
从Debian 的参考2.2.2 2002-11-30中我们可以知道:Debian二进制软件包的内问格式在deb(5)手册页中进行了描述。因为这个内部格式是一个会改变的主题(在 Debian的主发行版本之间),所以总是使用dpkg-deb(8)来操作deb文件。
从而dpkg-deb的手册页中我们可以知道:dpkg-deb打包,解包以及提供Debian归案的各种信息。如果必须,deb文件也可以单独用ar或tar来进行操作。使用dpkp安装或是从我们的系统移除软件包。
我 们可以在'/var/cache/apt/archives/'目录下发现许多deb文件。使用'dpkg-deb -I somepackage.deb'得到这个软件包在通常情况下所提供内容的一个概览。'dpkg-deb -c somepackage.deb'会列出将要安装的所有文件。
我们可以使用'ar tv somepackage.deb'来列出deb文件中内容。使用’x’选项可解压这些文件。
3 软件包结构
下面让我们更近一些的来检测一些软件包。例如,文件'parted_1.4.24-4_i386.deb'包含下面的三个文件:
$ ar tv parted_1.4.24-4_i386.deb
rw-r--r-- 0/0 4 Mar 28 13:46 2002 debian-binary
rw-r--r-- 0/0 1386 Mar 28 13:46 2002 control.tar.gz
rw-r--r-- 0/0 39772 Mar 28 13:46 2002 data.tar.gz
现在我们解压出所有的文件,包括tar文件中的内容。
3.1 debian-binary
这个文件的内容是"2.0\n"。这显示了deb文件格式的版本。对于2.0,所有其他的行都被忽略了。
3.2 data.tar.gz
data.tar.gz文件包含了所有将要被安装到目标路径中的文件:
drwxr-xr-x root/root 0 2002-03-28 13:44:57 ./
drwxr-xr-x root/root 0 2002-03-28 13:44:49 ./sbin/
-rwxr-xr-x root/root 31656 2002-03-28 13:44:49 ./sbin/parted
drwxr-xr-x root/root 0 2002-03-28 13:44:38 ./usr/
drwxr-xr-x root/root 0 2002-03-28 13:44:41 ./usr/share/
drwxr-xr-x root/root 0 2002-03-28 13:44:38 ./usr/share/man/
drwxr-xr-x root/root 0 2002-03-28 13:44:52 ./usr/share/man/man8/
-rw-r--r-- root/root 1608 2002-03-28 13:44:37 ./usr/share/man/man8/parted.8.gz
drwxr-xr-x root/root 0 2002-03-28 13:44:41 ./usr/share/doc/
drwxr-xr-x root/root 0 2002-03-28 13:44:52 ./usr/share/doc/parted/
-rw-r--r-- root/root 1880 2002-03-07 14:20:08 ./usr/share/doc/parted/README.Debian
-rw-r--r-- root/root 1347 2002-02-27 01:40:50 ./usr/share/doc/parted/copyright
-rw-r--r-- root/root 6444 2002-03-28 13:37:33 ./usr/share/doc/parted/changelog.Debian.gz
-rw-r--r-- root/root 15523 2002-03-28 02:36:43 ./usr/share/doc/parted/changelog.gz
他必须是deb归案中的最后一个文件。
3.3 control.tar.gz
在我们的这个例子中,这个文件包含下面的内容:
-rw-r--r-- 1 root root 1336 Mar 28 2002 control
-rw-r--r-- 1 root root 388 Mar 28 2002 md5sums
-rwxr-xr-x 1 root root 253 Mar 28 2002 postinst
-rwxr-xr-x 1 root root 194 Mar 28 2002 prerm
'md5sums'包含data.tar.gz中每一个文件的MD5校验码。在我们的这个例子中他的内容如下:
1d15dcfb6bb23751f76a2b7b844d3c57 sbin/parted
4eb9cc2e192f1b997cf13ff0b921af74 usr/share/man/man8/parted.8.gz
2f356768104a09092e26a6abb012c95e usr/share/doc/parted/README.Debian
a6259bd193f8f150c171c88df2158e3e usr/share/doc/parted/copyright
7f8078127a689d647586420184fc3953 usr/share/doc/parted/changelog.Debian.gz
98f217a3bf8a7407d66fd6ac8c5589b7 usr/share/doc/parted/changelog.gz
不要担心,md5sums文件以及postinst与prerm文件对于我们的第一个包来说并不是托管的。但是我们要注意到他们的存在,每一个官方的Debian软件包都会有他们存在的合适理由。
prerm与postinst小心的移除旧的文档文件,并且添加一个由doc指向share/doc的链接。
$ cat postinst
#!/bin/sh
set -e
# Automatically added by dh_installdocs
if [ "$1" = "configure" ]; then
if [ -d /usr/doc -a ! -e /usr/doc/parted -a -d /usr/share/doc/parted ]; then
ln -sf ../share/doc/parted /usr/doc/parted
fi
fi
# End automatically added section
$ cat prerm
#!/bin/sh
set -e
# Automatically added by dh_installdocs
if [ \( "$1" = "upgrade" -o "$1" = "remove" \) -a -L /usr/doc/parted ]; then
rm -f /usr/doc/parted
fi
# End automatically added section
而最后是最有趣的文件:
$ cat control
Package: parted
Version: 1.4.24-4
Section: admin
Priority: optional
Architecture: i386
Depends: e2fsprogs (>= 1.27-2), libc6 (>= 2.2.4-4), libncurses5 (>= \
5.2.20020112a-1), libparted1.4 (>= 1.4.13+14pre1), libreadline4 (>= \
4.2a-4), libuuid1
Suggests: parted-doc
Conflicts: fsresize
Replaces: fsresize
Installed-Size: 76
Maintainer: Timshel Knoll <
[email protected]>
Description: The GNU Parted disk partition resizing program
GNU Parted is a program that allows you to create, destroy,
resize, move and copy hard disk partitions. This is useful
for creating space for new operating systems, reorganizing
disk usage, and copying data to new hard disks.
.
This package contains the Parted binary and manual page.
.
Parted currently supports DOS, Mac, Sun, BSD, GPT and PC98
disklabels/partition tables, as well as a 'loop' (raw disk)
type which allows use on RAID/LVM. Filesystems supported are
ext2, ext3, FAT (FAT16 and FAT32) and linux-swap. Parted can
also detect HFS (Mac OS), JFS, NTFS, ReiserFS, UFS and XFS
filesystems, but cannot create/remove/resize/check these
filesystems yet.
.
The nature of this software means that any bugs could cause
massive data loss. While there are no known bugs at the moment,
they could exist, so please back up all important files before
running it, and do so at your own risk.
关于control文件的更为深入的信息我们可以通过命令'man 5 deb-control'来得到。
4 修改
现在是我们实验的时候了。在这里我们有一个简单的名为'linuxstatus’的Shell脚本,我们希望将他安装到'/usr/bin/linuxstatus'。所以首先我们要创建一个包含linuxstatus文件的名为debbian的目录:
$ mkdir -p ./debian/usr/bin
$ cp linuxstatus ./debian/usr/bin
4.1 control
我们首先从control文件开始。版本号与另外的Debian包版本号之间必须有一个短横线,如'1.1-1'。如果我们的程序只包含可移植的Shell脚本,我们可以使用'all'作为他的'Architecture'。
对于'Depends',我们需要查出我们新的软件包依赖于哪一个特定的文件或是程序。我们可以使用'dpkg -S <file>'来完成。如:
$ dkpg -S /bin/cat
coreutils: /bin/cat
然后如果我们要得到关于coreutils软件包更多的信息,我们可以使用命令'apt-cache showpkg coreutils'来进行查询,这个命令会告诉我们在我们当前的系统上所安装的版本号以及其他的一些信息。
另外还有其他的办法来得到同样的信息。有一个我们可以用来搜索Debian文件的网页:http://www.debian.org/distrib/packages。我们可以到这个页面的底部并填写相应的表单就可以查找我们要找的文件了。
最后还有一个名为'kpackage'的漂亮的GUI程序,这个程序提供了一个方便的包浏览选项,并且允许我们通过提供单个的文件名来查找相应的软件包。
‘Suggests', 'Conflicts', 与 'Replaces'等内容,如果不是必须的,我们就可以忽略掉。
所以我们的第一个'control'的结果如下:
Package: linuxstatus
Version: 1.1-1
Section: base
Priority: optional
Architecture: all
Depends: bash (>= 2.05a-11), textutils (>= 2.0-12), awk, procps (>= \
1:2.0.7-8), sed (>= 3.02-8), grep (>= 2.4.2-3), coreutils (>= 5.0-5)
Maintainer: Chr. Clemens Lee <
[email protected]>
Description: Linux system information
This script provides a broad overview of different
system aspects.
将control文件拷贝到另一个debian目录下的名为DEBIAN的目录。
$ mkdir -p debian/DEBIAN
$ find ./debian -type d | xargs chmod 755
$ cp control debian/DEBIAN
4.2 dpkg-deb
现在已经基本上完成了。我们只需要输入:
$ dpkg-deb --build debian
dpkg-deb: building package `linuxstatus' in `debian.deb'.
$ mv debian.deb linuxstatus_1.1-1_all.deb
呵呵,这要比我们想像的容易得多。现在我们就可以将这个软件包安装到我们的系统了,而我们的工作也就完成了。
root# dpkg -i ./linuxstatus_1.1-1_all.deb
我 们可以输入'linuxstatus'或是'ls -l /usr/bin/linuxstatus'来查看一下他是否可以正常工作。如果我们不再喜欢这个软件包,我们只需要输入'dpkg -r linuxstatus',然后检查一个这个软件包是否已经被卸载。如果我们要安装一个新版本,我们并不需要先移除旧的版本。
如果我们对于Debian软件包的版本号约定以及命名原则感兴趣,我们可以查看Debian引用中的相关部分。
5 双检测(Double Check)
现在我们得到了最初的印象,并且已经创建了我们自己的二进制包,现在我们需要更为严肃的来看一下我们所创建的软件包的质量。
5.1 lintian
Debian工程提供了一个lint工具来检查Debian软件包。这个工具名为lintian。如果在我们当前的系统上并没有安装这个工具,这是一个很好的时刻(apt-get install lintian).
现在我们在我们的新的软件包文件上使用这个工作:
$ lintian linuxstatus_1.1-1_all.deb
E: linuxstatus: binary-without-manpage linuxstatus
E: linuxstatus: no-copyright-file
W: linuxstatus: prerm-does-not-remove-usr-doc-link
W: linuxstatus: postinst-does-not-set-usr-doc-link
呣,看起来并不是完美的。我们丢失了man手册,copyright文件以及prerm与postinst脚本。
5.2 最小的文档
这里并不是讨论如何创建man手册的地方,而会有其他更多的相关的书籍来讨论这个话题。所以在这里我们作了一个小小的时间变形(time warp),假定我们已经在./man/man1/linuxstatus.1为我们的脚本创建一个完美的手册页。
同样的想法用于copyright文件。我们可以通过命令find /usr/share/doc -name "copyright"在/usr/share/doc目录发现足够多的例子。
所以下面的是我们的一个copyright文件的例子:
linuxstatus
Copyright: Chr. Clemens Lee <
[email protected]>
2002-12-07
The home page of linuxstatus is at:
http://www.kclee.de/clemens/unix/index.html#linuxstatus
The entire code base may be distributed under the terms of the GNU General
Public License (GPL), which appears immediately below. Alternatively, all
of the source code as any code derived from that code may instead be
distributed under the GNU Lesser General Public License (LGPL), at the
choice of the distributor. The complete text of the LGPL appears at the
bottom of this file.
See /usr/share/common-licenses/(GPL|LGPL)
对于prerm和postinst脚本,我们可以从上面的'parted'软件包中用同样的名字拷贝到我们的工程目录下。这些文件也可以很好的为我们工作。
现在我们可以再一次创建我们的软件包。在control文件中我们第一次将我们的版本号由1.1-1升到1.2-1(因为我们编写了一个新的手册页,所以我们增加了我们的内部发行号)。我们也需要拷贝这些新文件到合适的位置:
$ mkdir -p ./debian/usr/share/man/man1
$ mkdir -p ./debian/usr/share/doc/linuxstatus
$ find ./debian -type d | xargs chmod 755
$ cp ./man/man1/linuxstatus.1 ./debian/usr/share/man/man1
$ cp ./copyright ./debian/usr/share/doc/linuxstatus
$ cp ./prerm ./postinst ./debian/DEBIAN
$ gzip --best ./debian/usr/share/man/man1/linuxstatus.1
$
$ dpkg-deb --build debian
dpkg-deb: building package `linuxstatus' in `debian.deb'.
$ mv debian.deb linuxstatus_1.2-1_all.deb
Gzip是必须的,因为lintian希望手册页尽可能小的进行压缩。
5.3 fakeroot
现在我们的软件包就成了一个比较而言好一些的软件包了:
$ lintian linuxstatus_1.2-1_all.deb
E: linuxstatus: control-file-has-bad-owner prerm clemens/clemens != root/root
E: linuxstatus: control-file-has-bad-owner postinst clemens/clemens != root/root
E: linuxstatus: bad-owner-for-doc-file usr/share/doc/linuxstatus/ clemens/clemens != root/root
E: linuxstatus: bad-owner-for-doc-file usr/share/doc/linuxstatus/copyright clemens/clemens != root/root
E: linuxstatus: debian-changelog-file-missing
出 现了新的问题。当然我们并不会放弃。事实大问分的错误看起来都是一个问题。我们的文件是为用户和'clemens'组而打包的,然而我们假设大多数的用户 希望将他们安装为'root/root'。这个问题可以很容易的使用fakeroot工具来进行解决。让我们来修正这个问题:
$ fakeroot dpkg-deb --build debian
dpkg-deb: building package `linuxstatus' in `debian.deb'.
$ mv debian.deb linuxstatus_1.2-1_all.deb
$ lintian linuxstatus_1.2-1_all.deb
E: linuxstatus: debian-changelog-file-missing
不错,但是我们还需要添加另一个文件到软件包中。
5.4 更多的文档
在'doc/linuxstatus'目录下了除了'changelog'文件还需要一个'changelog.Debian'文件,这些都需要使用gizp进行压缩。
下面的是两个例子文件,'changelog':
linuxstatus (1.2-1)
* Made Debian package lintian clean.
-- Chr. Clemens Lee <
[email protected]> 2002-12-13
'changelog.Debian':
linuxstatus Debian maintainer and upstream author are identical.
Therefore see also normal changelog file for Debian changes.
现在我们最后一步如下:
$ cp ./changelog ./changelog.Debian ./debian/usr/share/doc/linuxstatus
$ gzip --best ./debian/usr/share/doc/linuxstatus/changelog
$ gzip --best ./debian/usr/share/doc/linuxstatus/changelog.Debian
$ fakeroot dpkg-deb --build ./debian
dpkg-deb: building package `linuxstatus' in `debian.deb'.
$ mv debian.deb linuxstatus_1.2-1_all.deb
$ lintian linuxstatus_1.2-1_all.deb
现在没有问题了。现在我们就可以使用root用户来安装这个新的软件包了。
root# dpkg -i ./linuxstatus_1.2-1_all.deb
(Reading database ... 97124 files and directories currently installed.)
Preparing to replace linuxstatus 1.1-1 (using linuxstatus_1.2-1_all.deb) ...
Unpacking replacement linuxstatus ...
Setting up linuxstatus (1.2-1) ...
6 小结
下面我们来小结一下我们创建一个Debian软件包所需的文件以及步骤:
所需的文件:
1 一个或是多个可执行的文件或是Shell脚本。
2 对于每一个可执行文件的手册页。
3 一个'control'文件。
4 一个'copyright'文件。
5 'changelog'与'changelog.Debian'文件。
设置临时的debian目录:
1 创建'debian/usr/bin'目录。
2 创建'debian/usr/share/man/man1'目录。
3 创建'debian/DEBIAN'目录。
4 创建'debian/usr/share/doc/<package_name>’。
5 确保debian目录的所有子目录的权限为0755。
拷贝文件到临时debian树:
1 拷贝可执行文件到'debian/usr/bin'目录。
2 拷贝手册页文件到'debian/usr/share/man/man1'目录。
3 拷贝'control'到'debian/DEBIAN'目录。
4 拷贝'copyright', 'changelog',与'changelog.Debian'文件到'debian/usr/share/doc/<package_name>’下。
5 在临时debian树下用'--best'选项压缩手册页,'copyright', 'changelog',与'changelog.Debian'。
创建与检测二进制Debian软件包:
1 在'debian'目录上使用'fakeroot'调用'dpkg-deb --build'。
2 将生成的'debian.deb'重命名为最终包含版本号与结构信息的软件包名。
3 使用'lintian’检测生成的deb软件包。