因产品的无法按 app 升级,发现产品中的组件已按包管理工具打包,但是却没有用上包管理工具的核心——依赖关系管理。本文研究包管理工具的依赖关系管理。
通常依赖关系管理分为安装时/运行时依赖和构建时依赖。这里主要讲安装时/运行时依赖。我所理解的安装时依赖即运行时依赖。
常见的包管理工具有 deb / rpm / pip / npm / rake 等,这里以 deb 为例。
详见 How to make a “Basic” .deb。为验证安装时依赖关系管理,创建 mydep_2.24-1。helloworld_1.0-1 依赖 mydep_2.24-1。
目录架构
- helloworld 软件包目录架构
1 | sunyongfeng@ubuntu:~/workshop/test$ tree helloworld_1.0-1 |
- mydep 软件包目录架构
1 | 4 directories, 2 files |
控制文件
该实验主要用到两个字段:
- Version,本 package 版本号
- Depends,本 package 依赖哪些软件包,及依赖的版本号是多少
- helloworld 控制文件
1 | sunyongfeng~/workshop/test$ cat helloworld_1.0-1/DEBIAN/control : |
- mydep 控制文件
1 | sunyongfeng~/workshop/test$ cat mydep_2.24-1/DEBIAN/control : |
打包
通过命令 dpkg-deb --build dir
打包。
1 | sunyongfeng@ubuntu:~/workshop/test$ dpkg-deb --build helloworld_1.0-1/ |
安装
依赖关系不成立,安装失败
如果先安装 helloworld,提示依赖的 mydep 未安装,失败。
1 | sunyongfeng@ubuntu:~/workshop/test$ sudo dpkg -i helloworld_1.0-1.deb |
依赖关系成立,安装成功
先安装 mydep。
1 | sunyongfeng@ubuntu:~/workshop/test$ sudo dpkg -i mydep_2.24-1.deb |
再安装 helloworld
1 | sunyongfeng@ubuntu:~/workshop/test$ sudo dpkg -i helloworld_1.0-1.deb |
卸载软件
如果先删除 mydep,会一般把依赖 mydep 的软件包都删除。
1 | sunyongfeng@ubuntu:~/workshop/test$ sudo apt-get remove mydep |
依赖关系数据库
deb 软件依赖关系数据库存放于 /var/lib/dpkg/status
,纯文本文件。比如 mydep 和 helloworld 的信息如下。
1 | sunyongfeng~/workshop/test$ sudo vi /var/lib/dpkg/status : |
hack 依赖关系数据库
由于没有看源码确认,通过删除依赖关系数据库中 helloworld 依赖 mydep 的 Depends 行 42480 Depends: mydep (>= 2.24)
。
通过删除 mydep 包,看 helloworld 会不会被连带删除确认依赖关系数据库是否生效。经验证,此时卸载 mydep 包,不会卸载 helloworld 包,与预期的相符。
1 | sunyongfeng@ubuntu:~/workshop/test$ sudo vi /var/lib/dpkg/status |
升级 mydep 版本,会不会提醒依赖它的 helloworld
答案是不会。
将 helloworld 的控制文件 Depends 行改为 42480 Depends: mydep (= 2.24)
,升级 mydep 为版本 2.25-1,此时不会提醒 helloworld。但是重新安装 helloworld 会进一步提醒。
因此对被依赖的软件包,如果升级为不向前兼容的版本,只能以“死给你看”的形式“通知”依赖它的软件包。
1 | sunyongfeng@ubuntu:~/workshop/test$ vi helloworld_1.0-1/DEBIAN/control |
参考资料
- http://tldp.org/HOWTO/html_single/Debian-Binary-Package-Building-HOWTO/
- https://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html
Written with StackEdit.