it-swarm.cn

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

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

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

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

106
Elazar Leibovich

像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天安装(更改?)的选择。

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

68
Mikel

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

20

粗糙,但是可以:

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
6
Dulantha

/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}。

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

4
Saint DanBert

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

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

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

3
Amias

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

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-[〜#〜] if [〜#〜]文件是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系统上进行过测试
2
not2qubit

GNU/Linux Debian没有用于解决此问题的内置工具,但是有关以标准方式安装的程序的所有信息都保存在带有program-name.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
PADYMKO

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

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