如何找出已安装的软件包自操作系统安装以来? 我不想知道所有已安装的软件包,只想知道那些不是初始操作系统安装的一部分,而是之后明确安装的软件包。
为了回答这个问题,我们假设是全新安装,因为我认为发行版升级会使事情复杂化。我更喜欢使用命令行,但如果命令或脚本不可用,GUI 解决方案也可以。
我快速浏览了 和 的手册页dpkg
,aptitude
但没有发现任何明显的问题。此外,apt-cache show package-name
或的输出dpkg -s pkg-name
似乎没有提供任何可以与操作系统安装日期(我必须弄清楚如何获取)进行比较的日期。
我的logwatch
服务器上每天都会发送已安装内容的通知。我猜它会解析 dpkg.log。我不确定这种方法是否可行,因为许多安装条目可能已被日志轮换,尤其是在较旧的系统上。理想情况下,这应该适用于任何系统、桌面或服务器。
如果输出可以包含当前安装的包的版本那就太好了,但这可能要求太多了,而且一旦我有了包名称,我总是可以稍后编写脚本。
答案1
所有 Ubuntu ISO([UKLX]buntu/Ubuntu-gnome)都附带.manifest
一个文件,其中包含 ISO 中所有预安装软件包的列表。您可以在任何 Ubuntu ISO 镜像上与这些 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 个文件中获取输入 - 第一个文件提供所有当前安装的软件包列表,第二个文件提供清单文件。 opt-3
会隐藏两个文件都有的行,并-2
隐藏只有第二个文件(即清单文件)才有的行。因此,最终您的输出仅包含只有文件 1 才有的行,并且会提供自安装操作系统以来您手动安装的软件包。
所以你有它。
编辑
如果你还想在输出中看到软件包名称旁边的软件包版本,正如 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
totally,这也会产生与上述命令相同的结果
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 命令如何工作的解释
答案2
这initial-status.gz 和 dpkg-query方法来自https://unix.stackexchange.com/a/80520/9132给出了符合我的需求的最准确、最简洁的列表。
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) \
)
为什么我喜欢它,而不喜欢其他的:
这显性比较弗林特的方法回答以及来自https://unix.stackexchange.com/a/3624/9132包括许多依赖项和其他可能被标记为“必需”并自动安装的包。例如,它列出了libvlc5和vlc 数据,而上面的方法只列出甚高频。
这历史日志方法来自https://askubuntu.com/a/250530/16741如果日志没有追溯到发布安装,则不会列出所有软件包。它还包含很多升级需要过滤掉的命令。
这dpkg --get-selections方法,这是一种公认的回答来自类似问题,列出了所有软件包和依赖项,包括随发行版一起安装的软件包和依赖项。它没有仅列出明确安装的软件包和依赖项。
答案3
非常感谢并祝贺那些想出这个绝妙脚本的人!
我想补充一下我的意见,并附上了从 $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