有什么方法可以查询dpkg
自系统基础安装以来添加/删除了哪些软件包?
我正在运行 Debian 5。
答案1
据我所知,没有直接的方法可以做到这一点。dpkg
数据库仅包含包的当前状态,因此任何历史记录都必须从日志中推断或解析。
简短回答(又称懒人单行回答)
dpkg-query -f='${Package}\n' -W | grep -vx "`grep 'Setting up' /var/log/installer/syslog | cut -d' ' -f8`"
解释
1. 获取安装程序安装的软件包列表
debian-installer
将其日志写入/var/log/installer
。那里有一个syslog
文件,我们可以grep
通过它查看安装了哪些软件包:
grep 'Setting up' /var/log/installer/syslog
请注意,我们正在寻找配置或者拆开而不是例如。选择因为我们需要所有软件包,包括作为依赖项安装的软件包。我们需要从中提取软件包名称:
grep 'Setting up' /var/log/installer/syslog | cut -d' ' -f8
2. 获取当前安装的软件包列表
现在我们需要一个当前安装的软件包列表来执行此reverse grep
操作。我们只需要软件包名称,例如不需要描述,以避免过滤掉太多内容,因此简单明了dpkg -l
并不好。我们可以改用dpkg-query
:
dpkg-query -f='${Package}\n' -W
3. 过滤启动时安装的软件包
剩下要做的就是从第二个列表中过滤掉第一个列表的内容。为此,我们使用grep -vx
.-v
表示“反向”,-x
(或--line-regex
)表示“精确”。后者仅匹配整行,以确保我们过滤掉例如。易于但不是资质。
以下是整个事情的经过:
# currently installed
current="`dpkg-query -f='${Package}\n' -W`"
# base install (let's also remove duplicates to make verification easier)
base="`grep 'Setting up' /var/log/installer/syslog | cut -d' ' -f8 | sort | uniq`"
# your answer
extra="`echo "$current" | grep -vx "$base"`"
removed="`echo "$base" | grep -vx "$current"`"
4. 验证结果
为了检查我们是否获得了正确的包,我们可以计算以下行:
echo "$base" | wc -l # 160
echo "$current" | wc -l # 1677
echo "$extra" | wc -l # 1517
echo "$removed" | wc -l # 0 (I used "netinst")
更新:如果/var/log/installer
不存在
/var/log/installer
如果软件包被清除,则会从系统中删除installation-report
。在这种情况下,我们可以尝试从最旧的文件中获取安装程序加载的软件包列表/var/log/dpkg.log.*
。
其中存在两个问题:
- 由于这些文件已经轮换,所以不能保证我们需要的信息仍然存在(在我的情况下仍然存在 - 安装于 2010-10-01 并且从那时起进行了大量更新)。
- 最旧的文件可能包含正在安装的软件包的日志后初始安装。
对于 (1) 我们无能为力。对于 (2),我们可以手动(可能通过时间戳)确定哪个包在 之前完成安装debian-installer
。就我而言,它似乎是os-prober
(我相信在某些情况下这可能很常见,因为它与 有关系grub
)。
以下是$base
使用此方法的示例代码:
last_installed="os-prober"
base_dpkglog="`zgrep ' install ' dpkg.log.8.gz | cut -d' ' -f4 | while read pkg; do
[ "$pkg" != "$last_installed" ] && echo $pkg || { echo $pkg; break; }
done | sort | uniq`"
快速验证一下:
echo "$base_dpkglog" | wc -l # 159
echo "$base" | wc -l # 160
diff -d <(echo "$base") <(echo "$base_dpkglog") # 31d30
# < dpkg