Deb 包(Debian 软件包)是一种用于在 Debian 及其衍生发行版(例如 Ubuntu)中分发和安装软件的标准包装格式。它们构成了 Debian Linux 发行版中的软件包管理系统的核心组成部分,旨在简化软件的分发、安装、更新和卸载流程。在本篇文章中,我们将深入探讨以下内容:
-
Deb 包基础知识:我们将介绍 Deb 包的基本概念,包括其结构、元数据和工作原理。您将了解如何识别、查找和理解 Deb 包,以及它们在系统中的重要性。
-
Deb 包制作:我们将详细讨论如何创建自定义的 Deb 软件包。这包括将您的应用程序打包为 Deb 包、定义软件包的依赖性、添加配置文件以及遵循 Debian 软件包制作的最佳实践。
-
Deb 包后续处理:一旦软件包被安装,我们将研究 Deb 包的后续处理。这包括管理已安装软件包的更新、卸载不再需要的软件包以及处理依赖性。
通过本文,您将深入了解 Deb 包的内部工作方式,并学会创建和管理它们,这对于在 Debian 及其相关发行版上进行软件分发和定制至关重要。
Deb 包基础知识
deb 文件是一个 Unix ar Archive 格式的文件,在 Linux 环境中,使用 ar命令可以查看 deb 所打包的具体内容,下面以tcpdump为例看一下
apt download tcpdump
下载tcpdump_4.99.0-2+deb11u1_arm64.deb
ar -t tcpdump_4.99.0-2+deb11u1_arm64.deb
debian-binary
control.tar.xz
data.tar.xz
很久很久以前,Linux 默认使用 gzip 作为压缩选择,所以那时候你会得到 control.tar.gz 这样的文件,但现在都是使用 xz 压缩格式了,它没有额外耗费太多算力的情况下压缩比率有大幅度的提高。gzip 虽然好,但毕竟是行程码风格的压缩算法,即使是对文本文件其压缩比也有限。
debian-binary
是一个文本文件,包含一个版本号戳记,这代表着 deb 文件格式的版本号,它目前通常都是 2.0。
control.tar.xz
control.tar.xz
是一个 Debian 软件包(.deb 文件)中的一个部分,它包含了软件包的控制信息。这些信息用于在安装、配置和卸载软件包时管理软件包的元数据。这个文件通常包含了一个叫做 control
的目录,其中包含了多个控制文件,这些文件以纯文本的方式描述了软件包的各种属性和依赖关系。
control
文件:这个文件是必需的,它包含了软件包的基本信息,如软件包的名称、版本、作者、描述等。这些信息用于在包管理系统中注册软件包并显示给用户。
Package: tcpdump
Version: 4.9.3-4ubuntu0.2
Architecture: amd64
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Installed-Size: 1088
Depends: libc6 (>= 2.14), libpcap0.8 (>= 1.5.1), libssl1.1 (>= 1.1.0), adduser
Suggests: apparmor (>= 2.3)
Breaks: apparmor-profiles-extra (<< 1.12~)
Replaces: apparmor-profiles-extra (<< 1.12~)
Section: net
Priority: optional
Multi-Arch: foreign
Homepage: https://www.tcpdump.org/
Description: command-line network traffic analyzer
This program allows you to dump the traffic on a network. tcpdump
is able to examine IPv4, ICMPv4, IPv6, ICMPv6, UDP, TCP, SNMP, AFS
BGP, RIP, PIM, DVMRP, IGMP, SMB, OSPF, NFS and many other packet
types.
.
It can be used to print out the headers of packets on a network
interface, filter packets that match a certain expression. You can
use this tool to track down network problems, to detect attacks
or to monitor network activities.
Original-Maintainer: Romain Francoise <rfrancoise@debian.org>
Package
: 软件包的名称,这里是 "tcpdump"。Version
: 软件包的版本,这里是 "4.9.3-4ubuntu0.2"。Architecture
: 软件包的体系结构,这里是 "amd64",表示适用于 64 位的 x86 架构。Maintainer
: 软件包的维护者或发布者的联系信息,这里是 "Ubuntu Developers ubuntu-devel-discuss@lists.ubuntu.com"。Installed-Size
: 软件包的安装大小(以 KB 为单位),这里是 1088 KB。Depends
: 软件包的依赖关系,指定了安装该软件包所需的其他软件包,包括 "libc6 (>= 2.14)", "libpcap0.8 (>= 1.5.1)", "libssl1.1 (>= 1.1.0)" 和 "adduser"。Suggests
: 软件包的建议安装软件包,这里建议安装 "apparmor (>= 2.3)"。Breaks
: 当安装这个软件包时,它会破坏 "apparmor-profiles-extra" 版本小于 "1.12~" 的软件包。Replaces
: 当安装这个软件包时,它会取代 "apparmor-profiles-extra" 版本小于 "1.12~" 的软件包。Section
: 软件包的所属领域,这里是 "net",表示网络相关的软件包。Priority
: 软件包的优先级,这里是 "optional",表示是一个可选的软件包。Multi-Arch
: 表示软件包支持多体系结构,这里是 "foreign",表示适用于不同的体系结构。Homepage
: 软件包的主页或官方网站,这里是 "https://www.tcpdump.org/"。Description
: 软件包的描述,提供了软件包的简要说明,功能和用途。Original-Maintainer
: 原始的软件包维护者的联系信息,这里是 "Romain Francoise rfrancoise@debian.org"。
preinst
、postinst
、prerm
、postrm
文件:这些文件包含了在软件包安装(inst
)和卸载(rm
)过程中执行的脚本。preinst
脚本通常用于在安装软件包之前执行一些操作,而postinst
脚本用于安装后的配置。同样,prerm
脚本用于卸载前的操作,而postrm
脚本用于卸载后的清理。
如下为postinst 该脚本通常在 Debian 软件包安装后执行。它包含了一些脚本命令,用于配置软件包的环境和执行必要的操作
#!/bin/sh -e
if ! getent group tcpdump >/dev/null 2>&1; then
addgroup --system --quiet tcpdump
fi
if ! getent passwd tcpdump >/dev/null 2>&1; then
adduser --system --quiet --ingroup tcpdump \
--no-create-home --home /nonexistent \
tcpdump
fi
# Automatically added by dh_apparmor/2.13.3-7ubuntu5.2
if [ "$1" = "configure" ]; then
APP_PROFILE="/etc/apparmor.d/usr.sbin.tcpdump"
if [ -f "$APP_PROFILE" ]; then
# Add the local/ include
LOCAL_APP_PROFILE="/etc/apparmor.d/local/usr.sbin.tcpdump"
test -e "$LOCAL_APP_PROFILE" || {
mkdir -p `dirname "$LOCAL_APP_PROFILE"`
install --mode 644 /dev/null "$LOCAL_APP_PROFILE"
}
# Reload the profile, including any abstraction updates
if aa-enabled --quiet 2>/dev/null; then
apparmor_parser -r -T -W "$APP_PROFILE" || true
fi
fi
fi
# End automatically added section
-
#!/bin/sh -e
: 这是脚本的 shebang 行,指定了脚本使用的 shell,这里是/bin/sh
,并启用了-e
标志,表示如果脚本中的任何命令失败,则整个脚本会立即退出。 -
if ! getent group tcpdump >/dev/null 2>&1; then
: 这是一个条件语句,用于检查是否存在名为 "tcpdump" 的用户组。如果不存在,它会使用addgroup
命令创建一个名为 "tcpdump" 的系统用户组。addgroup
命令用于添加用户组。 -
if ! getent passwd tcpdump >/dev/null 2>&1; then
: 类似于上面的条件语句,这次检查是否存在名为 "tcpdump" 的用户。如果不存在,它会使用adduser
命令创建一个名为 "tcpdump" 的系统用户,并将其添加到 "tcpdump" 用户组中。此用户不会有家目录(--no-create-home
),而其家目录会被设置为/nonexistent
。 -
接下来,脚本包含了一段用于处理 AppArmor 配置的代码。它检查是否执行了软件包的 "configure" 操作,并且如果存在名为 "/etc/apparmor.d/usr.sbin.tcpdump" 的 AppArmor 配置文件,则将其重新加载。这是通过使用
apparmor_parser
命令来实现的。
如下为postrm
该脚本通常在 Debian 软件包卸载后执行。它包含了一些脚本命令,用于在软件包卸载过程中执行必要的清理和操作
#!/bin/sh -e
case "$1" in
purge)
userdel tcpdump >/dev/null 2>&1 || true
groupdel tcpdump >/dev/null 2>&1 || true
;;
esac
# Automatically added by dh_apparmor/2.13.3-7ubuntu5.2
if [ "$1" = "purge" ] && ! [ -e "/etc/apparmor.d/usr.sbin.tcpdump" ] ; then
rm -f "/etc/apparmor.d/disable/usr.sbin.tcpdump" || true
rm -f "/etc/apparmor.d/force-complain/usr.sbin.tcpdump" || true
rm -f "/etc/apparmor.d/local/usr.sbin.tcpdump" || true
rm -f /var/cache/apparmor/*/"usr.sbin.tcpdump" || true
rmdir /etc/apparmor.d/disable 2>/dev/null || true
rmdir /etc/apparmor.d/local 2>/dev/null || true
rmdir /etc/apparmor.d 2>/dev/null || true
fi
# End automatically added section
-
case "$1" in
: 这是一个case
语句,根据脚本执行时的第一个参数$1
的值,选择不同的操作。在这个示例中,它检查$1
的值是否为 "purge",如果是,将执行相应的操作。 -
purge)
: 这是一个case
语句的分支,当$1
的值为 "purge" 时执行。它用于处理软件包的卸载操作。 -
userdel tcpdump >/dev/null 2>&1 || true
: 这个命令尝试删除名为 "tcpdump" 的用户。如果用户不存在,它将不会报告错误。这是通过userdel
命令来实现的。 -
groupdel tcpdump >/dev/null 2>&1 || true
: 类似于上面的命令,这次尝试删除名为 "tcpdump" 的用户组。如果用户组不存在,它将不会报告错误。这是通过groupdel
命令来实现的。 -
接下来,脚本包含了一段用于处理 AppArmor 配置的代码。它检查是否执行了软件包的 "purge" 操作,并且如果不存在名为 "/etc/apparmor.d/usr.sbin.tcpdump" 的 AppArmor 配置文件,将删除相关的 AppArmor 配置文件和目录。
conffiles
文件:这个文件列出了软件包安装的配置文件,以便在升级软件包时保留用户的自定义配置。md5sums
文件:这个文件包含了软件包中各个文件的校验和,以确保它们在传输和存储过程中没有被篡改。
data.tar.xz
data.tar.xz
是 Debian 软件包(.deb 文件)中的一个部分,它包含了软件包的实际文件和数据。这个文件通常包含了应该安装到系统的二进制文件、库、配置文件和其他资源。data.tar.xz
文件是通过压缩工具(通常是 xz
或其他压缩工具)进行压缩的,以减小软件包的大小并节省带宽。
当你安装一个 Debian 软件包时,系统会解压缩 data.tar.xz
并将其中的文件复制到系统的相应目录中,以完成软件包的安装。这些文件通常包括可执行文件、库文件、配置文件、文档和其他资源,这些资源是软件包的一部分,用于使软件包在系统上正常运行。如下为tcpdump 包的内容
data
├── etc
│ └── apparmor.d
│ └── usr.sbin.tcpdump
└── usr
├── sbin
│ └── tcpdump
└── share
├── doc
│ └── tcpdump
│ ├── changelog.Debian.gz
│ ├── copyright
│ ├── examples
│ │ ├── atime.awk
│ │ ├── packetdat.awk
│ │ ├── send-ack.awk
│ │ └── stime.awk
│ ├── NEWS.Debian.gz
│ ├── README.Debian
│ └── README.md.gz
└── man
└── man8
└── tcpdump.8.gz
-
etc
: 这是一个目录,通常包含配置文件。在这个示例中,它包含了一个名为 "apparmor.d" 的子目录,其中可能包含了与 AppArmor 安全配置相关的文件。apparmor.d
: 这是etc
目录的子目录,包含与 AppArmor 安全配置有关的文件。在这里,有一个名为 "usr.sbin.tcpdump" 的文件,这可能是与软件包 "tcpdump" 相关的 AppArmor 配置文件。
-
usr
: 这是一个目录,通常包含与用户相关的文件和数据。-
sbin
: 这是usr
目录的子目录,通常包含可执行的系统命令或工具。在这个示例中,有一个名为 "tcpdump" 的文件,这是软件包 "tcpdump" 的可执行文件。 -
share
: 这是usr
目录的另一个子目录,通常包含共享的数据和文档。-
doc
: 这是share
目录的子目录,包含软件包的文档文件。tcpdump
: 这是doc
目录的子目录,包含了 "tcpdump" 软件包的文档文件。其中包括一些文本文件和压缩的 changelog、README 等文件。
-
man
: 这是share
目录的子目录,通常包含手册页文件。man8
: 这是man
目录的子目录,包含第 8 节的手册页文件。在这个示例中,有一个名为 "tcpdump.8.gz" 的手册页文件,用于提供关于 "tcpdump" 命令的信息。
-
-
AppArmor(Application Armor)是一种Linux内核安全增强系统,用于限制应用程序的能力和权限,以增加系统的安全性。AppArmor通过创建应用程序特定的访问控制规则来实现这一目标,这些规则可以定义哪些文件、目录和系统资源可以由特定的应用程序访问。AppArmor的主要目标是减小应用程序的攻击面,降低系统遭受恶意行为的风险。
Deb 包制作
1、在原包基础上修改
#解压出包中的⽂件到extract⽬录下
dpkg -X tcpdump_4.9.3-4ubuntu0.2_amd64.deb extract/
#解压出包的控制信息extract/DEBIAN/下:
dpkg -e tcpdump_4.9.3-4ubuntu0.2_amd64.deb extract/DEBIAN/
#修改⽂件XXX
# 对修改后的内容重新进⾏打包⽣成deb包
dpkg-deb -b extract/
2、通用操作
也可以下载官方源码,在源码基础上打上补丁,再编译,这个需要:
安装必要软件build-essential devscripts
/etc/apt/sources.list 中的deb-src行去掉
#下载源码
apt-get source dash
#修改源码,打补丁或者手动修改
#进入编译
cd dash-*
debuild -us -uc # (-us -uc disables signing the package with GPG)
#在目录外生成deb包
Deb 包后续处理
1、安装
可以调用dpkg -i tcpdump_4.9.3-4ubuntu0.2_amd64.deb,大致流程如下
这个图示解释了在安装 Debian 软件包时不同的阶段和状态。让我们对这个图进行简要的解释:
-
Preinst Install: 当软件包正在被安装时,首先执行
preinst
脚本。这个脚本用于在软件包安装之前执行一些准备工作。 -
Postinst Configure: 如果
preinst
步骤成功完成,接下来执行postinst
脚本,用于配置软件包和执行其他必要的操作。如果preinst
和postinst
都成功执行,软件包的状态将被设置为 "Installed",表示安装完成。 -
Postrm Abort-Install: 如果在
preinst
安装阶段发生了错误,系统将调用postrm
脚本中的abort-install
部分。这个脚本用于处理在安装失败时的清理操作。如果abort-install
步骤成功,用户将收到错误消息,并且软件包状态将被设置为 "Not Installed",表示未成功安装。但如果postrm abort-install
部分也失败了,软件包将被留在一个不正常的状态下,即 "Half Installed, Reinst required"。这意味着即使你想要卸载它,软件包也需要重新安装。 -
Postinst Configure 失败: 如果在
postinst
配置阶段发生了错误,用户将收到错误消息,软件包的状态将被设置为 "Failed-Config",表示配置失败。
2、卸载
dpkg -r tcpdump
当卸载之前安装的软件包时,如果一切顺利,软件包将被保留在 "Config Files" 状态,这意味着在软件包处于 "Not Installed" 状态之前需要将其清除。
如果在 postrm
阶段出现问题,并且触发了 postinst abort-remove
脚本,那么软件包可能会处于一个奇怪的状态:它仍然标记为 "Installed",但实际上文件已不再存在。如果在卸载过程中的任何步骤失败,当再次尝试卸载软件包时,它将从之前停止的地方继续执行,也就是说,如果 prerm
步骤成功而 postrm
失败,它将从 postrm
继续执行。
这些不同的状态和脚本用于确保在软件包的安装、配置和卸载过程中,系统的状态始终可控,即使在过程中出现问题也能够正确处理。这有助于维护软件包管理的一致性和可靠性。
3、彻底删除(Purging)
dpkg -P tcpdump
-
首先,软件包的配置文件(conffiles)将被删除。这些配置文件包含了软件包的特定配置和设置。
-
接下来,将调用
postrm purge
脚本,用于执行清理操作。这个脚本通常包括删除软件包相关的文件和目录,以确保软件包完全从系统中清除。
4、升级
这一部分描述了软件包升级和降级的情况,以及可能涉及的脚本和状态变化。软件包的升级和降级是复杂的过程,它涉及多个脚本的执行和状态的变化,具体取决于操作是否成功。
升级软件包:
-
如果一切正常,四个脚本按顺序执行,包括
prerm upgrade
、preinst upgrade
、文件解压、postrm upgrade
和postinst configure
。 -
如果发生问题,例如在
preinst upgrade
阶段,它可能会导致软件包升级失败,而软件包可能会被留在一个半安装或失败配置的状态中。
降级软件包:
- 降级软件包通常是不安全的操作,因为它可能会导致不一致的状态。升级和降级过程实际上是相同的,只是版本互换。这包括
prerm upgrade
、preinst upgrade
、文件解压、postrm upgrade
和postinst configure
。
冲突的软件包:
- 当一个软件包被另一个与之冲突的软件包替换时,情况可能会更复杂。这种情况需要处理冲突,以确保系统的稳定性。这个文档没有提供详细的说明,但提到了可以找到有关冲突软件包的信息的链接。
5、调试和除错
在试制过程中,如果你的维护脚本写的不正确,那么安装 deb 可能会有意料之外的失败。这不是奇怪的事,问题在于此时 Debian 的包管理系统可能会进入到一种错误的状态。
如果安装一个 deb 导致了意外的终止,你可以采用下面的序列来做清理:
sudo mv /var/lib/dpkg/info/<packagename>.* /tmp/
sudo dpkg --remove --force-remove-reinstreq <packagename>
有时候,你可能疑惑于安装流程失败的原因。此时可以打开安装时的详细输出开关,例如:
sudo dpkg -D2 -i <deb-file>
man dpkg
能够查阅到 -D
的可能的取值:
Number Description
1 Generally helpful progress information
2 Invocation and status of maintainer scripts
10 Output for each file processed
100 Lots of output for each file processed
20 Output for each configuration file
200 Lots of output for each configuration file
40 Dependencies and conflicts
400 Lots of dependencies/conflicts output
10000 Trigger activation and processing
20000 Lots of output regarding triggers
40000 Silly amounts of output regarding triggers
1000 Lots of drivel about e.g. the dpkg/info dir
2000 Insane amounts of drivel
更多的时候是版本不匹配
可以在运行环境中打包