我的系统是 Debian Buster。我想用 git 跟踪已安装软件包的列表。
当我使用 列出已安装的软件包时dpkg -l
,该列表来自哪里?
我在 中找到了一些软件包信息/var/lib/dpkg/status
,但该文件包含的信息比我感兴趣的更多。还有其他地方存储软件包列表吗?
最好的跟踪文件是什么,以便我可以了解已安装的软件包、其版本或已卸载的软件包?
更新
我尝试使用 git 跟踪 /var/lib/dpkg/status ,但输出非常不清楚且令人困惑。状态信息太多了。我只需要跟踪已安装的软件包列表及其版本。类似于 dpkg -l 的输出。
dpkg -l 所示的软件包列表是否存储在某个文件中,还是每次都会动态生成?
我可以在 /var/lib/dpkg/ 中创建一个 git 存储库并在 git 中创建一些过滤器,以便基本上只跟踪 dpkg -l 的输出吗?或者也许每次我运行 git status` 时,列表都是动态创建的?或者任何其他解决方案,我不确定 git 提供什么可能性。
答案1
已安装的软件包列表是在/var/lib/dpkg/status
;这是规范的参考。已安装的软件包在该文件中通过其“安装正常已安装”状态发出信号。dpkg -l
每次运行时都会处理该文件,并使用其中存储的信息来生成其输出。
如果您想要一组更简单的数据来跟踪、简化比较,则必须在必要时生成它。
如果您只想跟踪已安装软件包的列表,您可以运行
dpkg --get-selections
git
定期并将其输出存储在用;跟踪的文件中因为你也想要版本,
dpkg -l
可能更合适。
正如所指出的马丁·康拉德,如果您希望能够使用此处生成的信息在以后恢复系统状态,您还应该跟踪手动安装的标记,我也会添加保留:
apt-mark showmanual
apt-mark showhold
您可以将以上所有内容添加到一个dpkg
钩子中,以跟踪系统的所有更改;例如,使用/etc/packages/
来保存文件(而不是/var/lib/dpkg
,它的“拥有”者dpkg
应该保持原样),创建一个名为 的文件/etc/dpkg/dpkg.cfg.d/package-history
,包含
post-invoke="if [ -x /usr/local/bin/package-history ]; then /usr/local/bin/package-history; fi"
和一个名为/usr/local/bin/package-history
包含的文件
#!/bin/sh
cd /etc/packages
dpkg --get-selections > selections
dpkg -l > list
apt-mark showhold > holds
apt-mark showmanual > manual
后者需要可执行:
sudo chmod 755 /usr/local/bin/package-history
上述所有命令的输出均已排序,因此无需对它们进行后处理。使用这些文件,您将能够准确恢复已安装的软件包状态,跟踪版本更改,还可以查看已删除但未清除的软件包。
您可以添加git commit
(首先检查更改)到package-history
脚本,或者用于etckeeper
跟踪 中文件的更改/etc/packages
,甚至可以创建/etc/packages
一个 git 存储库本身。使用dpkg
钩子确保文件将被更新任何包更改,无论是由 驱动apt
,还是dpkg
由任何其他基于dpkg
.如果您在package-history
脚本本身中提交,那么提交粒度将对应于dpkg
执行;如果你依赖etckeeper
,它就会对应涉及的动作etckeeper
。
要处理脚本中的提交,请添加
if [ "$(git status --porcelain | wc -l)" -gt 0 ]; then
git add *
git commit -m 'Update package information'
fi
到上面脚本的末尾;然后,您应该以 root 身份手动运行一次,以初始化 git 历史记录(在 后mkdir /etc/packages; git init /etc/packages
)。
答案2
包列表(如 所示)是否
dpkg -l
存储在某个文件中,还是每次都会动态生成?
斯蒂芬·基特的回答已经说明了这一点:/var/lib/dpkg/status
信息所在,其他一切都只是解析它。dpkg -l
以一种(默认)格式显示该信息,并且dpkg-query
(本质上就是这样dpkg -l
)可用于以其他格式显示该信息。
您可以从具有类似功能的包中获取灵感,etckeeper
。它添加了钩子来dpkg
提交对/etc
包更改的更改,并在提交消息中包含包列表。它不跟踪 git 中的包列表,因此您不能直接使用它。
它添加了像这样的钩子:
# cat apt/apt.conf.d/05etckeeper
DPkg::Pre-Invoke { "if [ -x /usr/bin/etckeeper ]; then etckeeper pre-install; fi"; };
DPkg::Post-Invoke { "if [ -x /usr/bin/etckeeper ]; then etckeeper post-install; fi"; };
RPM::Pre-Invoke { "if [ -x /usr/bin/etckeeper ]; then etckeeper pre-install; fi"; };
RPM::Post-Invoke { "if [ -x /usr/bin/etckeeper ]; then etckeeper post-install; fi"; };
etckeeper 操作本身调用dpkg-query -W -f '${Status}\t${Package} ${Version} ${Architecture}\n'
来获取包列表。
所以你可以做类似的事情。创建一个/etc/apt/99-track-packages
包含:
DPkg::Post-Invoke { "/some/script"; };
哪里/some/script
看起来像:
#! /bin/sh
cd /some/git/directory
dpkg -l >> list-of-packages
git commit -am 'some message'
然后每次 apt 调用时都会进行提交dpkg
。