deb包解析与打包
[TOC]
一、deb包结构
deb包中有两部分信息:
- 数据:在安装过程中直接拷贝到系统中的文件
- 控制:在安装和卸载过程中执行的脚本,为dpkg提供的包信息
以本次打包的openssh为例:
1 | . |
包目录中的DEBIAN目录中包含的就是控制信息,其它目录是数据信息,其它目录会被直接拷贝到系统根目录。
1) control文件
DEBIAN中的控制信息最重要的是control文件,以下是本次打包的openssh的control文件
1 | Package: ebaina-openssh |
其中:
- Package: 包名,使用dpkg安装后可通过
dpkg -l
查看安装的包 - Version: 软件版本
- Architecture:软件运行架构
- Maintainer:维护者
- Installed-Size:安装大小
- Depends: 软件的依赖项(包名),多个依赖项使用逗号隔开。可以指定依赖的版本
- Description:对软件包的描述,若描述打包时会报警告
2) 脚本
有四个脚本可以执行:preinst
postinst
prerm
psotrm
。分别在安装之前,安装之后,删除之前与删除之后执行。通过这些脚本可以在软件安装和卸载时自动执行一些其它操作,比如配置开机启动等。这些脚本只需添加可执行权限放在DEBIAN目录下即可。
二、deb打包与解包
如果对deb包还不够了解,可以下载deb包并解包,有利于进一步分析。
1 | apt 下载软件包但不安装(不需要管理员权限) |
可以在当前目录看到软件包ssh_1%3a7.6p1-4ubuntu0.7_all.deb
(可能版本不同)
1 | 创建存储解包文件的目录 |
为了详细了解DEBIAN的结构,可以下载不同的包分析共性。
打deb包
1 | pack dir:指定打包的目录 |
三、deb包的安装与包状态
安装与卸载软件包
1 | 安装软件包 |
1 | dpkg 允许同时安装多个软件包,dpkg会自行分析依赖,而不必按依赖顺序逐个安装 |
查看包状态
1 | dpkg -l |
1 | Name Version |
第一列表示软件包的状态,格式如下期望状态|当前状态|错误状态
期望状态
u:即 unknown,软件包未安装且用户未请求安装
i:即 install,用户请求安装该软件包
r:即 remove,用户请求卸载该软件包
p:即 purge,用户请求卸载该软件包并清理配置文件
h:即 hold,用户请求保持续当前软件包版本
当前状态
- n:即 not-installed,软件包未安装
- i:即 installed,软件包已安装并完成配置
- c:即 config-files,软件包已经被卸载,但是其配置文件未清理
- u:即 unpacked,软件包已经被解压缩,但还未配置
- f:即 half-configured,配置软件包时出现错误
- w:即 triggers-awaited,触发器等待
- t:即 triggers-pending,触发器未决
错误状态
- h:软件包被强制保持
- r:即 reinstall-required,需要卸载并重新安装
- x:软件包被破坏
dpkg的工作目录
这里说的工作目录是dpkg在运行时存储各种包信息的目录:/var/lib/dpkg
。其中包含status
文件以及info
目录。
在info目录中包含软件包的文件列表<pack name>.list
,在卸载软件包时会根据文件列表将文件删除。
除此之外还有各个软件包的脚本<pack name>.<script name>
,例如:ebaina-openssh.postinst
dpkg目录中的status则存储了每个软件包信息及其状态。
四、其它问题
无法卸载,提示Terminated
问题现象:
1
2
3Removing ebaina-haveged (1.9.2)...
Terminated
haveged: haveged: Stopping due to signal 15问题分析:在卸载时需要关闭对应的进程,所以在
prerm
脚本中通过ps加grep的方式查找进程PID,由于dpkg在卸载时的进程名也会包含包名。所以搜索出多个PID一起被杀死。其中包含dpkg卸载软件包的进程:1
21750 root 0:00 dpkg -r ebaina-haveged
1751 root 0:00 {ebaina-haveged.} /bin/sh /var/lib/dpkg/info/ebaina-haveged.prerm因此只需要在使用grep时避免将dpkg的进程包含在内即可
问题解决:
1
2
3HAVEGED_PID=`ps -e | grep -v grep | grep "haveged" | awk '{print $1}'`
改为
HAVEGED_PID=`ps -e | grep -v grep | grep "/haveged" | awk '{print $1}'`