查看 os install 之后安装了哪些软件包

查看 os install 之后安装了哪些软件包

如何找出已安装的软件包自操作系统安装以来? 我不想知道所有已安装的软件包,只想知道那些不是初始操作系统安装的一部分,而是之后明确安装的软件包。

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

我快速浏览了 和 的手册页dpkgaptitude但没有发现任何明显的问题。此外,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 版本列表例如,如果你有Trusty64 位系统,则清单链接为 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

或者,使用awktotally,这也会产生与上述命令相同的结果

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包括许多依赖项和其他可能被标记为“必需”并自动安装的包。例如,它列出了libvlc5vlc 数据,而上面的方法只列出甚高频

历史日志方法来自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

相关内容