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

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

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

评论

另请参阅如何获取apt-get安装的历史记录。

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

Askubuntu.com上的类似问题“如何列出所有已安装的软件包”。

#1 楼

像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


构建已安装软件包的列表

q4 312078q

加入2个列表

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


由于某种原因,它对我的​​打印差异不大,因此可能存在错误或错误关于--get-selections的含义的无效假设。

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

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


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

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

评论


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

– Elazar Leibovich
2011年5月4日下午6:53

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

–皮尔兹
16年11月22日在16:13

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

–克雷格·希克斯(Craig Hicks)
17年8月22日在5:26



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

–甜点
17年12月20日在19:54

如果apt或dpkg都没有存储安装/修改的日期时间,那么在2019年,这对于我来说似乎是不可接受的。我们依赖于grepping日志文件,该文件是否仍在计算机上?情况如何?

–theferrit32
19年2月14日在18:33

#2 楼

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才提供自动安装的注释。

评论


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

–克雷格·希克斯(Craig Hicks)
17年8月22日在5:38

#3 楼

粗糙,但是可以工作:

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 , ,  }'` : " ; 
    ( ( grep -A3 " ${lint}$" /var/lib/apt/extended_states | \
        grep '^Auto' > /dev/null ) && echo "Auto" ) || echo "Manual" ; 
done > pkgdatetime.txt


评论


Boo,嘶嘶声,用于解析ls的输出。请参阅mywiki.wooledge.org/ParsingLs,以获取有关为什么这样做很危险/固有错误的注释-较安全的选择是使用find -printf或stat --format生成可以明确解析的流。

–查尔斯·达菲(Charles Duffy)
2015年4月10日17:17



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

–not2qubit
18年4月26日在11:12

#4 楼

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


开始日期:{date} {time}
命令行:{command} {options ...}
安装:{package(version)},...,{package(version)},
...
结束日期:{date} {time}


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


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


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

当前执行的操作中,您可以发现信息您正在寻找,但需要进行一些取证处理才能提取出细节。

#5 楼

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

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


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

行说明:



ls -1t-按时间顺序获取所有dpkg.log*文件名

zcat -f-IF文件是gzip类型,然后将其解压缩,ELSE只需传递内容。

tac-cat的反向输出,逐行显示以确保我们获得正确的时间顺序。

grep-仅检查已安装或升级的软件包。

awk -F ':a'-从软件包名称中分离体系结构字段

column -t-漂亮地打印用空格分隔的列

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

输出为:

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系统上进行过测试


#6 楼

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

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


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

评论


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

– geoo
17-4-24在9:19



#7 楼

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



说明:



ls -rt输出按日期修改以相反顺序排列的文件,即最新文件位于列表末尾。

stat以易于阅读的形式打印文件的日期。

printf显示程序包名称和上次修改的日期。
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
18年4月26日在11:49

#8 楼

注意这一点是因为您提到欢迎其他分发答案。 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- query.html

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

#9 楼

它很粗糙,但是和其他解决方案一样快。日期格式为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 " "}' | 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 }'


评论


欢迎@ alexander-cave!请添加几行输出,以便人们可以看到期望的输出类型。

–not2qubit
18/09/5在19:50

#10 楼

使用apt中轮换的日志文件,您可以:

zcat -f /var/log/dpkg.log* | grep " install " | less


#11 楼

我已经使用以下命令在Kubuntu上实现了它:

列出软件包。
读取每个标准输入。
以“%”格式存储完整路径(路径|创建日期) n |%y“放入变量中。
将文件名存储到变量中
如果成功执行了前面的两个命令,则值将打印在一行中。

ls /var/lib/dpkg/info/*.list |while read xfile; do wpath=$(stat -c '%n|%y' ${xfile}) && wfile=$(basename ${xfile}) && printf "${wfile}|${wpath}\n" ;done


最好的问候,