如何查看 apt-get install 的历史记录?

如何查看我手动执行的apt-get install命令的历史记录?
对我来说,所有可用的方法似乎都显示了从Ubuntu安装开始就安装的所有内容。
如何查看自从我的系统安装过程完成以来的apt-get install的历史记录?

是的,你还能期望什么呢?你是想只显示那些从终端运行的命令,而不显示通过GUI或其他方式运行的命令吗?请编辑你的问题并澄清。 - terdon
@terdon 好的,我做了一个新的编辑。 - TellMeWhy
1dpkg的日志记录在/var/log/dpkg.log*中。 - Velkan
你也可以尝试运行 history | grep "apt-get install" - user364819
2@ParanoidPanda 这种方法在多个方面都存在问题。历史记录被截断,命令在其他终端中运行,命令从历史记录中删除或根本没有添加到历史记录中,通过脚本安装的命令,由其他用户运行的命令等等。 - Squidly
1@MrBones:我知道,并且在我的回答中已经说明了这一点(并在下面的评论中也提到了)。然而,OP要求一种查看所有手动执行apt-get install命令安装软件包的实例的方法,我提供了一个解决方案,除非历史文件以某种方式被修改(例如:条目被删除),否则可以提供这些信息。 - user364819
DevRobot,请验证一下我的回答,看看你是否得到了你想要的答案。 - Ravan
2相关(可能是重复的):如何通过命令行显示apt-get软件包管理历史记录? - Pablo Bianchi
8个回答

我认为这里给出的答案是我迄今为止见过的最好的方法,由kos提供。 虽然软件中心使用apt,但它安装的任何东西也会被列出。

命令如下:

zcat /var/log/apt/history.log.*.gz | cat - /var/log/apt/history.log | grep -Po '^Commandline: apt-get install (?!.*--reinstall)\K.*'

我回家后会测试一下,如果它有效的话,我会接受它 :) - TellMeWhy
不是这样的!看看更新内容:http://askubuntu.com/a/680405/320386 - kos
使用此命令更加安全: zcat /var/log/apt/history.log.*.gz | cat - /var/log/apt/history.log | grep -Po '^Commandline:(?=.* install ) \K.*' | sed '1,4d'grep -Po '^Commandline:(?=.* install ) \K.*'将仅过滤包含带有前导和尾随空格的“install”的apt-get命令,sed '1,4d' 可能依赖于特定的安装;在我的安装中,“1,4”删除了来自Ubiquity的确切条目数,这些是您要删除的内容。如果您的安装中数字相同,请告诉我,这样至少我们就有了一个基准 :| - kos
@kos 我得到了额外的行,比如 apt-get -o APT::Status-Fd=4 -o APT::Keep-Fds::=5 -o APT::Keep-Fds::=6 -q -y --no-remove install linux-generic 这个新命令。它们是Ubiquity的行吗? - Arronical
不,那些看起来像是来自软件更新程序;除了Ubiquity只运行一次的情况(例如aptdaemon的条目也会被该命令显示出来),没有办法区分用户运行的命令和某个apt-get前端运行的命令。不过最好的办法还是使用那个命令,至少可以排除掉Ubiquity的条目。 - kos
然而,只是想知道删除前4行是否总是安全的,你能确认一下zcat /var/log/apt/history.log.*.gz | cat - /var/log/apt/history.log | grep -Po '^Commandline:(?=.* install ) \K.*' | sed -n '1,4p'输出的内容是否类似于这个?(前两个条目没有换行,但它们非常庞大)。 - kos
不,它只输出了我安装的12个软件包中的前4行。这4行中的每一行都以'apt-get install'开头,然后是软件包的名称。@kos - Arronical
挺奇怪的,也许15.04版本有所不同(我猜你没有使用15.04版本,因为这已经是我第三次重新安装15.04了,而且每次开始的日志都完全一样)。那么就没办法了,无法安全地解析那些日志。谢谢。 - kos
是的,我正在使用14.04版本。我在回答中复制的命令对我来说有效,但我只手动安装了12个软件包,所以不能保证它对每个人都起作用! - Arronical
1你也可以使用apt install进行安装,或者在单词之间使用多个空格。 - Pablo Bianchi

只需在终端中键入以下命令即可查看所有安装日志。
grep " install " /var/log/dpkg.log

这个比已接受的解决方案更好,因为它列出了所有安装的包,包括依赖项。 - Manuel Durando

为了简化@Arronical的回答,我最近学到的一个很棒的技巧是可以使用zcat -qf来同时查看txt和txt gzipped文件。
zcat /var/log/apt/history.log.*.gz | cat - /var/log/apt/history.log | grep " install "

成为
zcat -qf /var/log/apt/history.log* | grep " install "

从man zcat:
   -q --quiet
          Suppress all warnings.
   -f --force
          Force  compression  or  decompression  even if the file has multiple links or the corre‐
          sponding file already exists, or if the compressed data is read from  or  written  to  a
          terminal.  If  the  input  data is not in a format recognized by gzip, and if the option
          --stdout is also given, copy the input data without change to the standard  output:  let
          zcat  behave  as  cat.  If -f is not given, and when not running in the background, gzip
          prompts to verify whether an existing file should be overwritten.

1正如我在评论中所提到的,还有其他情况。也许最好的方法就是zcat -qf /var/log/apt/history.log* | grep " install " - Pablo Bianchi

这里是一个脚本,它仅打印当前安装的顶级程序包,其中"顶级程序包"被定义为在没有其他atp程序包依赖的情况下的atp程序包。 如果这些顶级程序是通过atp或像synaptic这样的软件包管理器安装的,则它们是由用户手动选择的。
#!/bin/sh
NumDaysAgo=18
find /var/lib/dpkg/info -name "*.list" -mtime -$NumDaysAgo \
    -exec stat -c $'%y\t%n' {} \; | \
sed -e 's,/var/lib/dpkg/info/,,' -e 's,\.list,,' | \
sort -r | \
while read Date Time Xxx Pkg
do 
    lncnt=$(apt-cache --installed rdepends $Pkg | wc -l)
    if [ $lncnt -eq "2" ]
        then echo "$Date $Time $Pkg"
    fi
done
echo "JOB COMPLETED: $BASH_SOURCE"

包裹的打印顺序是反向的,这是基于用户更有可能希望尽快获取更新信息的假设,并且由于程序运行较慢。
程序流程:
- 程序首先通过读取/var/lib/dpkg/info/下的文件名,将所有已安装的包收集到一个列表中。文件的修改时间即为安装时间。 - 该列表按照反向顺序进行排序。 - 对于每个已安装的包$Pkg,调用apt-cache rdepends $Pkg来请求$Pkg的反向依赖关系。如果没有依赖关系,则它是一个顶级包,将打印出包的信息:日期 时间 包名
注意事项:
  • 脚本依赖于apt-cache rdepends $Pkg的输出格式,该格式是为人类眼睛设计的,并且在未来的apt版本中可能会发生变化。
  • 收集/var/lib/dpkg/info/目录下文件名的代码来自于this unix.stackexchange post。正如那位名叫'mikel'的帖子指出的那样,dpkg历史日志文件不可靠,因为它们在达到一定容量后会被轮换出去。
  • apt-chache的手册页
  • 调用apt-cache rdepends ...非常慢,可能是因为每次调用都需要通过迭代所有依赖项来计算。因此,上述脚本从最新的安装开始,以尽可能提供用户所需的即时满足感。
  • apt-cache之后的--installed标志检查了dpkg安装的软件包是否也是apt安装的。如果用户或其他安装软件绕过apt直接使用dpkg,这是可能的。尽管这种情况尚未经过测试,但我认为在标准输出或错误输出中会打印出一些明显的信息。
  • 输出不包括后来成为更高级软件包依赖的手动选择的软件包。输出还可以包括通过其他第三方安装软件通过apt安装的软件包,因此它们并不是真正的手动安装。然而,如果输出的目的是作为设置从备份的/home目录恢复的Linux的基础,其中包括了这些第三方软件,则此输出是合适的。
  • 一些软件包名称包含版本号,而其他一些则不包含。只是提醒大家注意这个事实。

如果你想要获取关于apt-get install命令的历史记录,请使用以下命令:
grep "apt-get install" .bash_history

输出:

ravan@ravan:~$ grep "apt-get install" .bash_history

sudo apt-get install --no-install-recommends ubuntu-mate-core ubuntu-mate-desktop
sudo apt-get install xfce4
sudo apt-get install xfce4.12
sudo apt-get install pgadmin
sudo apt-get install touchegg
sudo apt-get install aptitude
sudo apt-get install aptitude
sudo gedit .bash_history | grep "apt-get install" 
sudo apt-get installvim
grep "apt-get install" .bash_history
cat .bash_history | grep "apt-get install" 

有关其他信息,请参考额外信息

/var/log/apt/目录下,还有更详细的安装信息,包括history.loghistory.log.X.gz文件以及term.logterm.log.X.gz文件。

如果您只想获取包含apt-get命令的历史记录,请执行以下操作:

history | grep apt-get


apt-mark showmanual 显示了在操作系统安装时安装的所有软件包,而不仅仅是那些实际上是手动安装的。这种行为方式确实有些奇怪! - Arronical
2这并不一定提供关于历史的具体细节。人们需要查看的是/var/log/apt/history.log和类似的文件。你只能得到手动选择和自动选择的软件包列表。从这个答案中,你无法获得任何关于安装、卸载、升级等方面的时间顺序历史记录。 - Thomas Ward
@Arronical - apt-mark showmanual的man页在哪里?我在Ubuntu 16.04 LTS的apt man页上找不到它:http://manpages.ubuntu.com/manpages/xenial/zh_CN/man8/apt.8.html. - Craig Hicks
@CraigHicks http://manpages.ubuntu.com/manpages/xenial/zh_CN/man8/apt-mark.8.html - Arronical

如果你想查看你已安装的所有内容,请运行以下命令:
sudo apt-get install [package]

如果你没有搞乱bash历史记录,也不想查看其他用户(或所有用户)的这种安装类型的历史记录,那么你只需运行以下命令:
history | grep "apt-get install"

这样你应该能得到大部分相关的结果。

1我会得到全部的历史记录吗? - TellMeWhy
@DevRobot:除非您手动更改了.bash_history文件中带有apt-get install的条目,或者删除了该文件,否则该命令将显示您在用户账户上执行包含字符串apt-get install的命令的所有实例(即使您以root身份运行命令,因此不完全是作为用户账户运行命令 - 即使用sudo运行命令)。 - user364819
2如果您输入的命令超过200条,可能会出现问题。 - Arronical
2在提出主张时,我们期望有证据支持。;-) - Rinzwind
@Arronical:真的吗?我不知道.bash_history文件中有200个命令的限制,而且在我的系统上肯定没有这样的限制。你能否请你澄清一下你的意思。 - user364819
1我个人认为500是默认值(http://www.gnu.org/software/bash/manual/html_node/Bash-History-Facilities.html)。 - Rinzwind
哎呀,我是说2000个命令,我想这是history命令默认显示的命令数量,但我可能是自己想象的!现在查看一下... - Arronical
history显示了由$HISTSIZE环境变量指定的命令数量,这些命令来自您的.bash_history文件。在14.04服务器安装中,默认情况下似乎设置为1000。@Rinzwind,感谢你让我检查一下! - Arronical

请注意,在安装之前可以设置一些参数,就像virtualmin脚本在安装过程中所做的那样:apt-get -y install packagename。
因此,如果您想捕获所有的安装命令,您需要更改正则表达式查询。
zcat -qf /var/log/apt/history.log* | grep -Po '^Commandline: apt-get.*install (?!.*--reinstall)\K.*'

为了查看您安装、卸载、重新安装等操作的情况,可以获取有关apt-get安装过程的更多信息。
答案可以修改为一个别名:
alias apted='zcat /var/log/apt/history.log.*.gz | cat - /var/log/apt/history.log | fgrep Commandline: | cut -d " " -f 2- | grep -P "^|install"'