Debian制作DEB包的方法

构建环境说明

包的相关知识

  1. DEB包的结构
1
2
3
4
5
6
7
8
9
10
11
12
13
# DEB包就是把文件放到根目录对应的路径里,然后再在包管理器里注册一下
# DEB包通常遵循一定的文件结构,包括以下主要部分:

控制信息 DEBIAN/control 包含软件包的的包名、版本、架构、作者、描述等
配置文件 DEBIAN/conffiles 软件包配置文件的路径,这些文件在软件包升级时会特别处理,以确保用户自定义的配置不会丢失
装前脚本 DEBIAN/preinst 在解包 data.tar.gz 之前执行的脚本
装后脚本 DEBIAN/postinst 在软件包安装后要执行的命令,可以用于执行清理工作、添加启动脚本等操作
卸前脚本 DEBIAN/prerm 卸载时,在删除 实际数据 之前运行的脚本
卸后脚本 DEBIAN/postrm 在软件包卸载后要执行的命令,可以用于执行卸载后的清理操作
实际数据 usr/ 软件包的实际文件和目录结构,这些文件会被释放到系统根目录对应的路径里
文档文件 usr/share/doc 一些软件包可能包括文档文件,这些文件通常存储在该目录下

# 注意:必须要有一个DEBIAN文件夹(权限755),最精简的状态下只需要有 control 文件就可以了,其余文件可以不创建
  1. 控制信息的相关知识
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# DEBIAN/control 文件内的属性信息必须以字母或者数字开头,最简单的模板如下:
Package: python3.10 # 包名,缺少会报错
Version: 3.10.9-1+leux # 版本,缺少会报错
Architecture: amd64 # 架构,缺少会报错
Maintainer: leux # 作者,缺少会警告
Description: Python 3.10 Version # 描述,缺少会警告

# DEBIAN/control 文件内的其他可用属性信息:
Package: # 软件包名称
Version: # 软件包版本
Section: # 软件包所属的部分
Priority: # 软件包的优先级
Architecture: # 软件包的体系结构
Essential: # 是否是必要软件包
Depends: # 软件包的依赖关系
Pre-Depends: # 软件包的先决依赖
Recommends: # 建议安装的软件包
Suggests: # 建议但非必需的软件包
Conflicts: # 与其他软件包的冲突
Provides: # 软件包提供的功能
Replaces: # 替代其他软件包
Maintainer: # 维护者的信息
Description: # 软件包的简短描述
# 软件包的详细描述(可以跨多行)
  1. 预处理脚本的相关知识
1
2
3
4
5
# 这几个预处理的脚本记得需要执行权限(chmod 755)
DEBIAN/preinst # 安装前执行的脚本
DEBIAN/postinst # 安装后执行的脚本
DEBIAN/prerm # 卸载前执行的脚本
DEBIAN/postrm # 卸载后执行的脚本

制作DEB例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 因为打包前文件是什么用户所有和权限,打包后就是什么样的,所以建议全程用root用户执行
# 下面以手动编译Python源码后安装到了XXX/下,将其制作成DEB包为例
mkdir XXX/DEBIAN/ && cd XXX/

# 写入软件包的相关信息
cat << EOF > XXX/DEBIAN/control
Package: python3.10
Version: 3.10.9-1
Architecture: arm64
Maintainer: leux <leux@xxx.org>
Description: The Python Language (Version 3.10.9)
EOF

# 安装之后运行的脚本
cat << EOF > XXX/DEBIAN/postinst
#!/bin/sh

ln -sf /usr/local/bin/python3.10 /usr/sbin/python
echo "/usr/local/lib/python3.10/kvmd-packages" > /usr/local/lib/python3.10/site-packages/site-packages.pth
EOF

# 卸载之前运行的脚本
cat << EOF > XXX/DEBIAN/prerm
#!/bin/sh

rm /usr/sbin/python
rm /usr/local/lib/python3.10/site-packages/site-packages.pth
EOF

cd ../
chmod 0755 XXX/DEBIAN/p* # 加权
dpkg -b XXX/ Python3.10.deb # 打包
sudo dpkg -i Python3.10.deb # 安装

其他相关知识

  1. 解包修改后再打包
1
2
3
4
5
6
7
8
# 解包到指定文件夹
dpkg-deb -X fruity-pikvm_0.2_arm64.deb pikvm/

# 解包 DEBIAN/ 等文件到指定文件夹
dpkg-deb -e fruity-pikvm_0.2_arm64.deb pikvm/DEBIAN/

# 修改后再次打回包
dpkg-deb -b pikvm/ fruity-pikvm_rk3588_arm64.deb
  1. 已安装包的信息查看
1
2
3
4
5
6
# 已安装的包查看其文件与信息
/var/lib/dpkg/status
/var/lib/dpkg/info/python3.postinst
/var/lib/dpkg/info/python3.postrm
/var/lib/dpkg/info/python3.preinst
/var/lib/dpkg/info/python3.prerm
  1. 找出源码编译的软件需要的依赖包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 找出编译该软件所需安装的开发依赖包 (该命令来自 devscripts 包)
# 该软件使用帮助:dpkg-depcheck [options] <command>
-a, --all # 报告用于运行 <command> 的所有包
-b, --build-depends # 不报告使用的 build-essential 或 essential 包或它们的任何(直接或间接)依赖项
-d, --ignore-dev-deps # 不显示所使用的 -dev 软件包的直接依赖项所使用的软件包
-m, --min-deps # 输出所需的最小软件包集,同时考虑直接依赖关系

# 以从源码编译Python为例
tar -xzvf Python-3.10.9.tgz && cd Python-3.10.9
dpkg-depcheck -d ./configure --enable-optimizations

# 从输出中找到编译所需要的依赖包
Packages needed:
libfl-dev:amd64
libffi-dev:amd64
libmount-dev:amd64
libnl-3-dev:amd64
libperl5.36:amd64
adwaita-icon-theme
zlib1g-dev:amd64
xfonts-utils
libevent-dev
udev
uuid-dev:amd64
libpkgconf3:amd64
libjpeg62-turbo-dev:amd64
iso-codes
libselinux1-dev:amd64
pkgconf-bin
libglib2.0-dev:amd64
shared-mime-info
libxml2-dev:amd64
libbsd-dev:amd64
libnl-genl-3-dev:amd64
libmd-dev:amd64
libicu-dev:amd64
systemd
libncurses-dev:amd64
libssl-dev:amd64
libsigsegv2:amd64
libsepol-dev:amd64
libpcre2-dev:amd64
poppler-data
libelf-dev:amd64
mailcap
libblkid-dev:amd64
gawk
  1. 找出二进制文件依赖库的包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 先找到 /usr/bin/foo 的编译依赖,可以执行:
leux@B650:~$ objdump -p /usr/local/bin/python3.10 | grep NEEDED
NEEDED libm.so.6
NEEDED libc.so.6

# 列出包含该库的包,可得知该包依赖 libc6:amd64
leux@B650:~$ dpkg -S libm.so.6
libc6-i386: /lib32/libm.so.6
libc6:amd64: /lib/x86_64-linux-gnu/libm.so.6
libc6-armhf-cross: /usr/arm-linux-gnueabihf/lib/libm.so.6
libc6-x32: /libx32/libm.so.6
libc6-arm64-cross: /usr/aarch64-linux-gnu/lib/libm.so.6
leux@B650:~$ dpkg -S libc.so.6
libc6-x32: /libx32/libc.so.6
libc6-dev-i386: /usr/share/gdb/auto-load/lib32/libc.so.6-gdb.py
libc6-dev:amd64: /usr/share/gdb/auto-load/lib/x86_64-linux-gnu/libc.so.6-gdb.py
libc6:amd64: /lib/x86_64-linux-gnu/libc.so.6
libc6-arm64-cross: /usr/aarch64-linux-gnu/lib/libc.so.6
libc6-dev-x32: /usr/share/gdb/auto-load/libx32/libc.so.6-gdb.py
libc6-armhf-cross: /usr/arm-linux-gnueabihf/lib/libc.so.6
libc6-i386: /lib32/libc.so.6
leux@B650:~$
  1. 命令dpkg的相关参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
dpkg-deb -b|--build <directory> [<deb>]		# 将指定文件夹内所有打包成DEB包
dpkg-deb -e|--control <deb> [<directory>] # 仅解包 DEBIAN/ 下等相关文件到指定文件夹
dpkg-deb -x|--extract <deb> <directory> # 解包到指定文件夹,但无 DEBIAN/control 之类的文件
dpkg-deb -X|--vextract <deb> <directory> # 解包到指定文件夹并显示解包日志

dpkg -c <file.deb> # 列出deb包中的内容
dpkg --info <file.deb> # 查看deb包信息
dpkg -i|--install <file.deb> # 安装软件包
dpkg -r|--remove <package> # 仅卸载软件包但保留与其关联的配置文件
dpkg -P|--purge <package> # 完全删除软件包及其配置文件
dpkg --force-all -r <package> # 强制卸载包。‌这将删除软件包及其所有相关文件,‌包括配置文件
dpkg -L|--listfiles <package> # 列出已安装软件包的文件列表
dpkg -s|--status <package> # 显示软件包的详细信息,即 DEBIAN/control
dpkg -S|--search <pattern> # 在已安装的软件包中搜索名称或描述中包含<pattern>的软件包
dpkg -l|--list [<pattern>...] # 列出所有已安装的软件包

# ii就是已经安装的软件。 rc则表示已经被删除,但配置文件还存在。un表示卸载
leux@B650:~$ dpkg --list python3.10
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-================-============-===================================
ii python3.10 3.10.9-1+leux1u2 amd64 Used For fruity-pikvm_0.2_arm64.deb