![如何获取 x 时间之后新安装的软件包列表(不包括 x 时间之后删除的软件包)?](https://linux22.com/image/866691/%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96%20x%20%E6%97%B6%E9%97%B4%E4%B9%8B%E5%90%8E%E6%96%B0%E5%AE%89%E8%A3%85%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%E5%88%97%E8%A1%A8%EF%BC%88%E4%B8%8D%E5%8C%85%E6%8B%AC%20x%20%E6%97%B6%E9%97%B4%E4%B9%8B%E5%90%8E%E5%88%A0%E9%99%A4%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%EF%BC%89%EF%BC%9F.png)
从中/var/log/apt/history.log
可以x
根据时间戳检索时间内已安装和已删除的软件包的列表,但是编辑文件相当烦人,所以我正在寻找一个(一组)命令来以软件包名称列表的形式获取在时间戳之后安装的有效软件包列表x_0
(=在时间戳之后安装的软件包x_0
减去在时间戳之后删除的软件包x_0
)。
software-center
仅按时间顺序显示更改,并且synaptic
没有表示安装时间的列。dpkg-query
看起来很有希望,但我非常感谢可以在几分钟而不是几天内解决这个问题的人的帮助(后者适用于我自己)。
我正在运行 Ubuntu 14.10。
答案1
似乎dpkg
没有明确显示有关软件包安装日期的任何信息。
因此,对于一次运行,我将使用类似以下的一行代码:
cat /var/log/apt/history.log |perl -lne 'next unless /^Start-Date: ([^ ]+)/ && $1 ge "2015-04-26" .. 1; next unless /^(Install|Purge|Remove): (.*)$/; $c = $1; $s = $2; $s =~ s/\([^\)]*\)//g; @packages = map { /^(.*?):/ ? $1 : $_} split /\s*,\s*/, $s; if ($c=~/^Install$/){ $h{$_} = 1 for @packages;} if ($c=~/^(Purge|Remove)$/) {delete $h{$_} for @packages;} END{print for sort keys %h;}'
开始日期(x_0)已在命令("2015-04-26"
)中硬编码。
对于不时使用来说,更适合的是一个独立的脚本,如下所示installed_packages.pl
:
#!/usr/bin/perl
# use as follows:
# ./installed_packages.pl '2015-04-26' /var/log/apt/history.log
# or
# ./installed_packages.pl '2015-04-26 16:08:36' /var/log/apt/history.log
use strict;
use warnings;
# the script expects start date as first argument
my $START_DATE = shift @ARGV;
# hash (dict) to accumulate installed & not removed packages
my %installed;
# flag to mark the beginning of "interesting" period of time
my $start = 0;
# loop over lines from the input file
while (my $line = <>){
# remove end-of-line character
chomp $line;
# skip everything until date becomes greater (or equal) than our x_0
$start ||= $line =~ /^Start-Date: ([^ ]+)/ && $1 ge $START_DATE;
next unless $start;
# we're only interested in lines like
# Install: tupi-data:amd64 (0.2+git02-3build1, automatic), tupi:amd64 (0.2+git02-3build1), libquazip0:amd64 (0.6.2-0ubuntu1, automatic)
# or
# Remove: aptitude-common:amd64 (0.6.8.2-1ubuntu4)
# + separate action (install/remove/purge) from package list
next unless $line =~ /^(Install|Purge|Remove): (.*)$/;
my ($action, $packages_str) = ($1, $2);
# remove versions from the list (they're in parentheses)
$packages_str =~ s/\(.*?\)//g;
# split single line into array of package names
my @packages = split /\s*,\s*/, $packages_str;
# remove architecture name (comes after ':')
s/:.*// for @packages;
# if packages have been installed, add them all to the hash (dict) of installed packages
if ($action =~ /^Install$/ ){
$installed{$_} = 1 for @packages;
}
# if packages have been removed, remove them all from the hash (dict) of installed packages
if ($action =~ /^(Purge|Remove)$/) {
delete $installed{$_} for @packages;
}
}
# print all installed and not removed packages, in alphabetical order
for my $p ( sort keys %installed ){
print "$p\n";
}
用法:
./installed_packages.pl '2015-04-26' /var/log/apt/history.log
或者
perl ./installed_packages.pl '2015-04-26' /var/log/apt/history.log
对于频繁的交互使用,我会添加脚本参数的验证(开始日期的格式),实现-h
开关以显示简短的帮助,并可能将开始日期转换为命名开关(--start
)。
祝你好运!
答案2
我拿了源代码此回复并略微扩大。
附加值是您还可以获得已清除和已删除的包,并且可以使用 过滤输出grep
。
列出已安装的软件包:
./installed_packages.pl '2015-04-28' /var/log/apt/history.log | grep Installed:
或者对于已清除或已移除:
./installed_packages.pl '2015-04-28' /var/log/apt/history.log | grep -Ei '(Purged|Removed)'
源代码:
#!/usr/bin/perl
# use as follows:
# ./installed_packages.pl '2015-04-26' /var/log/apt/history.log
# or
# ./installed_packages.pl '2015-04-26 16:08:36' /var/log/apt/history.log
use strict;
use warnings;
# the script expects start date as first argument
my $START_DATE = shift @ARGV;
# hash (dict) to accumulate installed & not removed packages
my %installed;
my %removed;
my %purged;
# flag to mark the beginning of "interesting" period of time
my $start = 0;
# loop over lines from the input file
while (my $line = <>){
# remove end-of-line character
chomp $line;
# skip everything until date becomes greater (or equal) than our x_0
$start ||= $line =~ /^Start-Date: ([^ ]+)/ && $1 ge $START_DATE;
next unless $start;
# we're only interested in lines like
# Install: tupi-data:amd64 (0.2+git02-3build1, automatic), tupi:amd64 (0.2+git02-3build1), libquazip0:amd64 (0.6.2-0ubuntu1, automatic)
# or
# Remove: aptitude-common:amd64 (0.6.8.2-1ubuntu4)
# + separate action (install/remove/purge) from package list
next unless $line =~ /^(Install|Purge|Remove): (.*)$/;
my ($action, $packages_str) = ($1, $2);
# remove versions from the list (they're in parentheses)
# $packages_str =~ s/\(.*?\)//g;
# split single line into array of package names
my @packages = split /\s*,\s*/, $packages_str;
# remove architecture name (comes after ':')
s/:.*// for @packages;
# if packages have been installed, add them all to the hash (dict) of installed packages
if ($action =~ /^Install$/ ){
$installed{$_} = 1 for @packages;
}
# if packages have been removed, add them all to the hash (dict) of installed packages
if ($action =~ /^Remove$/) {
$removed{$_} = 1 for @packages;
}
# if packages have been purged, add them all to the hash (dict) of installed packages
if ($action =~ /^Purge$/) {
$purged{$_} = 1 for @packages;
}
}
# print all installed and not removed packages, in alphabetical order
for my $p ( sort keys %installed ){
print "Installed: $p\n";
}
for my $p ( sort keys %removed ){
print "Removed: $p\n";
}
for my $p ( sort keys %removed ){
print "Purged: $p\n";
}