找出os安装后安装的软件包

如何找到自安装操作系统以来安装的软件包 ? 我不想知道所有安装的软件包,只知道那些不属于初始操作系统安装的软件包,并且之后已经明确安装。

为了这个问题,让我们假设一个全新的安装,因为我认为发行版升级会使问题复杂化。 我更喜欢使用命令行,但如果命令或脚本不可用,GUI解决方案就可以了。

我已经快速浏览了dpkgaptitude的手册页,但没有看到任何明显的东西。 此外, apt-cache show package-namedpkg -s pkg-name似乎没有给出任何可以与操作系统安装日期进行比较的日期(我必须弄清楚如何获得) 。

我在服务器上有logwatch ,它每天发送已安装内容的通知。 我的猜测是它解析了dpkg.log。 我不确定这种方法是否是一种解决方案,因为许多安装条目可能已被logrotated出来,特别是在旧系统上。 理想情况下,这适用于任何系统,桌面或服务器。

如果输出可能包含当前安装的软件包的版本也会很棒,但这可能要求太多,并且我可以在以后拥有软件包名称时始终编写脚本。

所有Ubuntu ISO([UKLX] buntu / Ubuntu-gnome)都附带.manifest文件,其中包含ISO中所有预安装软件包的列表。 您可以在任何Ubuntu ISO镜像上的那些下载目录中找到那些清单文件。 以可用的Ubuntu版本列表为例; 例如,如果您有Trusty 64位,那么清单链接将是http://releases.ubuntu.com/trusty/ubuntu-14.04.2-desktop-amd64.manifest 。

所以一旦你有了这个文件,只需将它中的软件包列表与使用comm命令在Ubuntu中所有已安装软件包的列表进行比较

 $ curl -O http://releases.ubuntu.com/trusty/ubuntu-14.04-desktop-amd64.manifest $ comm -23 <( dpkg --get-selections | awk '$2 ~ /^(install|hold)/ { print $1 }' | sort ) \ <( awk '{ print $1 }' ubuntu-14.04-desktop-amd64.manifest | sort ) 

为了解释comm作用,它从2个文件中获取输入 - 第一个提供所有当前安装的包的列表,第二个提供清单文件。 -3 opt抑制两个文件都有的行, -2抑制只有第二个文件(清单文件)的行。 因此,最后您的输出仅包含仅包含文件的行,并且为您提供自安装操作系统以来手动安装的包。

所以你有它。

编辑

如果您还希望在输出中看到包名称旁边的包版本,正如Slyvain Pineau指出的那样,将上面的comm命令传递给xargs dpkg-query -W -f='${binary:Package} ${Version}\n'所以它变成了

 $ comm -23 <( dpkg --get-selections | awk '$2 ~ /^(install|hold)/ { print $1 }' | sort ) \ <( awk '{ print $1 }' ubuntu-14.04-desktop-amd64.manifest | sort ) | \ xargs dpkg-query -W -f='${binary:Package} ${Version}\n 

或者,完全用awk ,这也给出与上面命令相同的结果

 awk 'FNR==NR {arr[$1];next} !($1 in arr) { print $0 }' ubuntu-14.04-desktop-amd64.manifest <( dpkg-query -W -f='${binary:Package} ${Version}\n' ) 

有关awk cmd如何工作的说明,请参阅此链接

https://unix.stackexchange.com/a/80520/9132中的initial-status.gz和dpkg-query方法为我的需求提供了最准确,最简洁的列表。

 comm -13 \ <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort) \ <(comm -23 \ <(dpkg-query -W -f='${Package}\n' | sed 1d | sort) \ <(apt-mark showauto | sort) \ ) 

为什么我喜欢它,而不是其他人:

Flint的答案和https://unix.stackexchange.com/a/3624/9132的清单比较方法包括许多依赖项和其他可能标记为“必需”并自动安装的软件包。 例如,它列出了libvlc5vlc-data ,而上面的方法仅列出了vlc

如果日志没有返回到发布安装,则https://askubuntu.com/a/250530/16741中的history.log方法将不会列出所有软件包。 它还包含许多需要过滤的升级命令。

dpkg --get-selections方法是类似问题的可接受答案 ,它列出了所有软件包和依赖项,包括随该版本一起安装的软件包和依赖项。 它不会仅列出明确安装的那些。

非常感谢和祝贺那些想出脚本gem的人!
我想加上我的2美分,我加上了我从$ info中推断的安装日期。
我没有掌握$ info文件更新与否的详细信息以及何时更新,但它在实践中有效。
我的脚本列出了安装后添加的非依赖包的最新更新。
给它定期检查,我看到我会手动记录,没有一次错过。
也就是说,出于同样的原因安装了批量的数据包。 不幸的是,更新打破了这个顺序
在系统升级之后,我有一个我添加的软件包列表,升级没有更新,然后是它所做的。
整齐! 请享用。

 info='/var/lib/dpkg/info/' comm -13 > /tmp/packages \ <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort) \ <(comm -23 \ <(dpkg-query -W -f='${Package}\n' | sed 1d | sort) \ <(apt-mark showauto | sort) \ ) while read n; do echo $(ls -ltr --time-style=long-iso $info$n.* $info$n:i386.* $info$n:amd64.* 2>/dev/null \ | tail -n 1 | perl -pe 's/.*([0-9]{4}?-.*:[0-9]{2}?).*/\1/') $n done < /tmp/packages | sort