使用 git 跟踪已安装软件包的列表

使用 git 跟踪已安装软件包的列表

我的系统是 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

相关内容