按安装日期列出基于apt的系统上的软件包


104

如何按安装日期列出已安装的软件包?

我需要在debian / ubuntu上执行此操作。其他分布的答案也将很好。

我安装了很多东西来编译某些代码,并且我想获得必须安装的软件包的列表。



1
我一直在搜索“ apt发布日期”,但没有运气,也许此评论会对将来的Google员工有所帮助。
ThorSummoner 2014年

Answers:


66

像Red Hat这样基于RPM的发行版很容易:

rpm -qa --last

在Debian和其他基于dpkg的发行版上,您的特定问题也很容易:

grep install /var/log/dpkg.log

除非日志文件已轮换,在这种情况下,您应该尝试:

grep install /var/log/dpkg.log /var/log/dpkg.log.1

在一般情况下,dpkgapt似乎并不跟踪安装日期,在缺乏任何此类领域的持续dpkg-query手册页。

最终,旧/var/log/dpkg.log.*文件将通过日志轮换被删除,因此不能保证这种方式可以为您提供系统的整个历史记录。

几次出现的建议(例如,该线程)是查看/var/lib/dpkg/info目录。那里的文件建议您尝试以下操作:

ls -t /var/lib/dpkg/info/*.list | sed -e 's/\.list$//' | head -n 50

为了回答有关选择的问题,这是第一遍。

按日期构建软件包列表

$ find /var/lib/dpkg/info -name "*.list" -exec stat -c $'%n\t%y' {} \; | \
    sed -e 's,/var/lib/dpkg/info/,,' -e 's,\.list\t,\t,' | \
    sort > ~/dpkglist.dates

构建已安装软件包的列表

$ dpkg --get-selections | sed -ne '/\tinstall$/{s/[[:space:]].*//;p}' | \
    sort > ~/dpkglist.selections

加入2名单

$ join -1 1 -2 1 -t $'\t' ~/dpkglist.selections ~/dpkglist.dates \
    > ~/dpkglist.selectiondates

出于某种原因,它对我而言并没有太多差异,因此可能--get-selections意味着错误或无效的假设。

您显然可以通过使用find . -mtime -<days>或来限制软件包head -n <lines>,并根据需要更改输出格式,例如

$ find /var/lib/dpkg/info -name "*.list" -mtime -4 | \
    sed -e 's,/var/lib/dpkg/info/,,' -e 's,\.list$,,' | \
    sort > ~/dpkglist.recent

$ join -1 1 -2 1 -t $'\t' ~/dpkglist.selections ~/dpkglist.recent \
    > ~/dpkglist.recentselections

仅列出过去4天安装(更改?)的选择。

您可能还可以sort在验证使用的排序顺序后删除命令dpkg --get-selections,并使find命令更有效。


8
我通常apt-get比更加喜欢rpm,但是现在debian由于未在数据库中保存安装日期而得到-1。debian技巧包括所有已安装的软件包,而不仅仅是选定的软件包,但这是一个好的开始。
Elazar Leibovich

对于Debian,如果您half-installed这样做,您的工作量就会减少(删除条目):grep install\ /var/log/dpkg.log
Pierz

@Mikel-好答案。我扩展了'gather /var/lib/dpkg/info/*.list文件信息',并添加了代码以过滤除“顶级程序包”(没有其他atp程序包依赖的atp程序包)之外的所有代码。该< askubuntu.com/a/948532/723997 > 帖子回答了以下问题:“如何查看手动执行的apt-get安装命令的历史记录? ”。
克雷格·希克斯

1
Debian / Ubuntu:grep " install " /var/log/dpkg.log仅列出“安装”行,而不显示“状态”行。
甜点

如果apt和dpkg都没有存储安装/修改的日期时间,那么在2019年,这对于我来说似乎是不可接受的。情况如何?
theferrit32

20

Mikel展示了如何在dpkg级别执行此操作。特别/var/lib/dpkg/info/$packagename.list是在安装软件包时创建(以后不进行修改)。

如果您使用了APT工具(由于您担心自动和手动安装的软件包,因此可以这么做),则中有一个历史记录/var/log/apt/history.log。只要它没有旋转,它就会跟踪所有APT的安装,升级和删除,并带有标记为自动安装的软件包的注释。这是一个相当新的功能,在APT 0.7.26中引入,因此在Debian中它出现在挤压状态。在Ubuntu中,具有10.04版本,history.log但直到10.10版本才提供自动安装的注释。


1
正如Mikel指出的那样:“最终,旧的/var/log/dpkg.log.*文件将通过日志轮换被删除,因此不能保证这种方式可以为您提供系统的整个历史记录。” 请参阅此< askubuntu.com/a/948532/723997 >答案,以了解如何检测当前的顶级软件包(意味着没有其他软件包依赖的软件包)
Craig Hicks

5

粗糙,但是可以:

for fillo in `ls -tr /var/lib/dpkg/info/*.list` ; 
    do basename ${fillo} | sed 's/.list$//g' ; 
done > forens.txt

ls -ltr /var/lib/dpkg/info/*.list > forentime.txt

for lint in `cat forens.txt` ; do 
    echo -n "[ ${lint} Installed ] : " ; 
    echo -n "`grep /${lint}.list forentime.txt | awk '{ print $6, $7, $8 }'` : " ; 
    ( ( grep -A3 " ${lint}$" /var/lib/apt/extended_states | \
        grep '^Auto' > /dev/null ) && echo "Auto" ) || echo "Manual" ; 
done > pkgdatetime.txt

2
Boo,嘶嘶声,用于解析的输出ls。请参阅mywiki.wooledge.org/ParsingLs,以获取有关为什么这样做很危险/本质上是越野车的注释-较安全的选择是使用find -printfstat --format生成可以明确解析的流。
查尔斯·达菲

@CharlesDuffy不错的链接,但是为了简单起见,使用ls -al --time-style=long-iso应该会有所帮助。另外,可能还没有听说有人会用\n\t\r\v它的名字命名APT软件包。
not2qubit

4

/var/log/apt/history.log文件的格式笨拙,恕我直言。

开始日期:{date} {time}命令行:{command} {options ...}安装:{package(version)},...,{package(version)},... End-Date:{date } {时间}

我本来希望有更多日志文件格式的记录

{date} {time} {tab} {package} {tab} {version} {tab} {command} {options} \ n

或一些XML,不仅显示{package},还显示任何{dependencies}。

按照当前的实施方式,您可以发现所需的信息,但是需要进行一些取证处理才能提取出详细信息。


3

这对我在Debian系统上有效,我猜测文件格式自2011年以来已经更改。该系统非常新,因此我不希望它在较旧的系统上运行,尽管这可能只需要解压缩日志并使用引用所有这些的问题。

grep 'install ' /var/log/dpkg.log.1 | sort | cut -f1,2,4 -d' '

文件每一行的前两个字段/var/log/dpkg.log是日期和时间。请注意grep部分中带有install的尾随空格,这是因为升级可以触发安装,但是如果我理解正确的话,您想知道用户安装了什么。


1
就是我做的 简单。但是您可以使用zgrep,您所有的.gz日志都会像zgrep'install'/var/log/dpkg.log*一样被搜索。在“安装”一词前放置空格,以防止讨厌的“半安装”。我必须使用cut -f1,5来获取包名字段。当然,最终旧的原木会旋转出来。
geoO

2

这是每个人都想要和需要的一线客:

for x in $(ls -1t /var/log/dpkg.log*); do zcat -f $x |tac |grep -e " install " -e " upgrade "; done |awk -F ":a" '{print $1 " :a" $2}' |column -t

结果将按时间顺序显示所有(新)安装升级的软件包。

行说明:

  • ls -1t- dpkg.log*按时间顺序获取所有文件名
  • zcat -f- 如果文件是gzip类型,然后解压缩,则ELSE只是传递内容。
  • tac- 逐行反向输出cat,以确保我们获得正确的时间顺序。
  • grep-仅检查已安装升级的软件包。
  • awk -F ':a'-将架构字段与包名称分开
  • column -t -漂亮地打印以空格分隔的列

一个人当然想为此做一个别名,但是不幸的是,这是不可能的,因为awk依赖于单引号和双引号。在这方面,最好将其放入bash脚本中,并在字段列中:更好地处理分隔符以用于其他体系结构

输出为:

2018-03-06  18:09:47  upgrade  libgomp1                     :armhf  6.3.0-18+rpi1                 6.3.0-18+rpi1+deb9u1
2018-03-05  15:56:23  install  mpg123                       :armhf  <none>                        1.23.8-1
2018-03-05  15:56:23  install  libout123-0                  :armhf  <none>                        1.23.8-1
2018-01-22  17:09:45  install  libmailtools-perl            :all    <none>                        2.18-1
2018-01-22  17:09:44  install  libnet-smtp-ssl-perl         :all    <none>                        1.04-1

退税:

  • 如上所示,它仅适用于ARM体系结构,并且需要对体系结构字段分隔符进行一些修改
  • 需要放入脚本中以方便别名
  • 尚未在其他* nix系统上进行过测试

1

注意这一点是因为您提到欢迎其他分发答案。rpm具有大量的输出格式标签,其中之一是INSTALLTIME。(wget以示例为例)

rpm -qi wget --qf "%{NAME},%{INSTALLTIME}\n" | tail -n 1
wget,1454014156

可以用几种方法格式化。我以这种方式使用它:

rpm -qi wget --qf "%{NAME},%{INSTALLTIME:date}\n" | tail -n 1
wget,Thu 28 Jan 2016 03:49:16 PM EST

这两页提供了大量有关解决RPM元数据问题的信息:

http://www.rpm.org/max-rpm/s1-rpm-query-parts.html

http://www.rpm.org/max-rpm/s1-rpm-query-handy-queries.html

对这些信息进行排序将为您的问题提供一个可行的解决方案。


1

GNU / Linux Debian没有用于解决此问题的内置工具,但是有关以标准方式安装的程序的所有信息都保存在文件程序名.list的文件中,该文件位于/ var / lib / dpkg / info /位置但是,那里没有有关手动安装程序的信息。


一个长的单行解决方案

for file_list in `ls -rt /var/lib/dpkg/info/*.list`; do \
    stat_result=$(stat --format=%y "$file_list"); \
    printf "%-50s %s\n" $(basename $file_list .list) "$stat_result"; \
done

说明

  1. ls -rt以相反的顺序输出按日期修改排序的文件,最新文件位于列表末尾。
  2. stat 以易于阅读的形式打印文件的日期。
  3. printf 显示软件包名称及其最后修改日期。
  4. 整个for循环从最旧到最新打印软件包名称和日期。

输出示例(被截断):

.........................................
gnome-system-log                            2016-09-17 16:31:58.000000000 +0300
libyelp0                                    2016-09-17 16:32:00.000000000 +0300
gnome-system-monitor                        2016-09-17 16:32:00.000000000 +0300
yelp-xsl                                    2016-09-17 16:32:01.000000000 +0300
yelp                                        2016-09-17 16:32:03.000000000 +0300
gnome-user-guide                            2016-09-17 16:32:18.000000000 +0300
libapache2-mod-dnssd                        2016-09-17 16:32:19.000000000 +0300
.........................................
linux-compiler-gcc-4.8-x86                  2017-02-26 20:11:02.800756429 +0200
linux-headers-3.16.0-4-amd64                2017-02-26 20:11:10.463446327 +0200
linux-headers-3.16.0-4-common               2017-02-26 20:11:17.414555037 +0200
linux-libc-dev:amd64                        2017-02-26 20:11:21.126184016 +0200
openssl                                     2017-02-26 20:11:22.094098618 +0200
unzip                                       2017-02-26 20:11:23.118013331 +0200
wireless-regdb                              2017-02-26 20:11:23.929949143 +0200
nodejs                                      2017-02-26 20:11:33.321424052 +0200
nasm                                        2017-02-28 16:41:17.013509727 +0200
librecode0:amd64                            2017-03-01 10:38:49.817962640 +0200
libuchardet0                                2017-03-01 10:41:10.860098788 +0200
tree                                        2017-03-04 14:32:12.251787763 +0200
libtar0                                     2017-03-07 09:51:46.609746789 +0200
libtar-dev                                  2017-03-07 09:51:47.129753987 +0200

该解决方案的主要缺陷是,它在生产中没有经过充分的测试。


这是一个很好的解决方案,几乎可以完成工作。唯一的缺点是(1)速度非常慢,以及(2)仅显示软件包的最新更新时间,而不显示任何以前的版本。当然,这不是单线的问题,而是dpkg如何不跟踪中的历史记录/var/lib/dpkg/info/。这也是为什么使用/var/log/dpkg.log*可能是首选的原因。
not2qubit

1

它很粗糙,但是和其他解决方案一样快。日期格式是yyyymmddhhmmss,这意味着位或重新排序以及格式删除会导致可以排序的数字。

非常感谢其他解决方案,该列表按安装顺序列出了软件包名称,这些名称可以在内置的复制操作系统中使用。

find /var/lib/dpkg/info -name "*.list" -exec stat -c $'%n\t%y' {} \; \
| sed -e 's,/var/lib/dpkg/info/,,' -e 's,\.list\t,\t,' \
| sort | awk '{print $2$3" "$1}' | sed '0,/RE/s/-//' \
| sed '0,/RE/s/-//' | sed '0,/RE/s/://' | sed '0,/RE/s/://' \
| sed '0,/RE/s/\\.//' | sed 's/:armhf//' | sort | awk '{print $2}'

欢迎@ alexander-cave!请添加几行输出,以便人们可以看到期望的输出类型。
not2qubit
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.