如何找到手动安装的包?

我在我的计算机上安装了一个普通的Ubuntu 10.10,并通过apt-get安装了一些软件。 上周我设法打破了一切,从头开始,我需要重新安装我的软件。 有没有办法创建一个包含我手动安装的所有软件包的列表?

所以它会给我一个像texlive, ...而不是texlive, texlive-dep1, textlive-dep2, ...以及所有标准包被删除的列表?

如果我能够以某种方式找出我已经删除的常规安装中的哪些程序,那也将是非常棒的!


更新2015-05-23:我现在在我的系统上使用Ansible作为配置管理。 在那里我指定要安装的包。 这符合目标,在新系统上安装所有程序,甚至更好。 所以这个问题可能是进入一些轻量级配置管理的问题。

有了这个建议,我假设您的旧安装仍然会启动!

要在另一台计算机上复制一组软件包:

在系统A上,运行:

 dpkg --get-selections | grep -v deinstall > my-selections 

my-selections文件移到系统B.

在系统B上,运行:

 dpkg --set-selections < my-selections 

然后:

 sudo apt-get dselect-upgrade 

重要说明:如果您已从非标准存储库和/或PPA安装了软件包,则还需要从System A复制/etc/apt/sources.list/etc/apt/sources.list的内容在运行升级之前到系统B.

您也可以使用dpkg查看已删除的内容(注意:这还包括您手动安装删除的软件包):

 dpkg --get-selections | grep deinstall 

您可以在终端中查看结果,当然还可以重定向到文件。

来自superuser.com的这个post给出了这个解决方案:

 aptitude search '?installed ?not(?automatic)' 

如果你的apt日志在/ var / log / apt中,那么这样的东西应该有效:

 gunzip -c /var/log/apt/history.log.*.gz | grep "apt-get install" 

或者如果你想摆脱输出中的一些重复垃圾:

 gunzip -c /var/log/apt/history.log.*.gz | grep "apt-get install" \ | cut -f4- -d" " | sort | uniq 

你可以使用apt-mark ,但我推荐debfoster :

 sudo apt-get install debfoster sudo debfoster 

这将检查所有已安装的软件包,并确定哪些软件包正在安装其他软件包:

 texlive-full is keeping the following 161 packages installed: cm-super cm-super-minimal context doc-base dvipng feynmf fonts-gfs-artemisia fonts-gfs-baskerville fonts-gfs-bodoni-classic ... Keep texlive-full? [Ynpsiuqx?], [H]elp: 

当你对每个问题回答“y”时(只需按Enter键快速移动),debfoster将收集包列表并逐行写入文件。 默认情况下,这是在/var/lib/debfoster/keepers 。 它看起来像这样:

 gnome-do texlive-full ... 

我通过/etc/debfoster.conf配置debfoster将此列表放在/etc/debfoster-keepers keepers中 ,并使用etckeeper跟踪该文件以保留历史记录和备份。 这里的答案显示了如何从换行符分隔的文本文件安装包列表:

 sudo apt-mark manual $(cat debfoster-keepers) 

注意这里的限制,你清除的包在它们前面有一个’ – ‘。 所以你想在调用apt-mark之前删除这些行。

即使debfoster的网站说debfoster被弃用而不赞成aptitude,我更喜欢debfoster的快速和简单的配置。 它将您置于包数据库的中间,让您清理,使自动手动包更加明显。

在debfoster提示符下键入“h”以解释您的选项。 输入“?” 查看包装说明。 这里的方法可能有用。

 comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort -u) 

提供所有手动安装的软件包(不是系统软件包,不是依赖项)。 例如,它显示了build-essential但不是gcc

我终于明白了:

 outfile="$(mktemp)" pattern='(\[INSTALLIEREN\]|\[INSTALL\])' if [[ -f "/var/log/aptitude.1.gz" ]] then gunzip -c /var/log/aptitude.*.gz | grep -E "$pattern" | awk '{ print $2; }' > "$outfile" fi if [[ -f "/var/log/aptitude" ]] then grep -E "$pattern" "/var/log/aptitude" | awk '{ print $2; }' >> "$outfile" fi sort "$outfile" rm "$outfile" 

我可以通过打开/ var / log / apt /中的日志文件来提取所有内容

然后我进入并手动过滤掉apt-get安装包。 可能有一种方法以编程方式执行此操作,但我不知道它。

对于那些喜欢使用apt- *工具的人来说,有一个apt-mark实用程序可以同时查询和修改手动/自动状态。

 apt-mark showmanual 

您还可以为感兴趣的包指定模式:

 apt-mark showmanual qemu\* 
 cd /var/log/apt cat history.log | grep Commandline 

这样您就可以看到过去执行的命令列表。

如果您需要更多信息,请删除grep代码:

 less history.log 

如果日志被压缩(即以gz结尾)

 gunzip  

完成后再拉链,你可以这样做:

 gzip  

我没有看到任何解决方案在这里为我工作,我已经安装了相当多的deb包与dpkg和一些我特别寻找的项目丢失。

一个相当冗长的一个衬垫,但方便复制和粘贴将是:

 export DPKG_INITIAL=$(mktemp) DPKG_INSTALLED=$(mktemp) DPKG_CUSTOM=$(mktemp) DPKG_DEPS=$(mktemp) zgrep -E '^Package' /var/log/installer/initial-status.gz | awk '{ print $2 }' > $DPKG_INITIAL ; awk '$3 !~ /install|remove|purge/ { next } { gsub(/remove|purge/, "uninstall", $3) ; gsub(/:.+/, "", $4) ; a[$4]=$3 } END { for (p in a) { if (a[p] == "install") { print p } } }' /var/log/dpkg.log | sort -u > $DPKG_INSTALLED ; comm -23 installed initial > $DPKG_CUSTOM ; function rdep() { apt-cache rdepends $1 | tail -n +3 | sed -e 's/^ //' -e '/^ /d' | cut -d':' -f1 | sort -u; } ; echo "$(for i in $(cat custom) ; do rdep $i ; done)" | sort -u > $DPKG_DEPS ; comm -23 custom deps > my-packages ; rm $DPKG_INITIAL $DPKG_INSTALLED $DPKG_CUSTOM $DPKG_DEPS 

上面的命令将包列表保存到当前工作目录中名为my-packages的文件中。

说明

我首先构建了一个包列表,其中包含安装期间选择的包的基线。

 zgrep -E '^Package' /var/log/installer/initial-status.gz | awk '{ print $2 }' > initial 

随后安装了一长串项目。

 awk '$3 !~ /install|remove|purge/ { next } { gsub(/remove|purge/, "uninstall", $3) ; gsub(/:.+/, "", $4) ; a[$4]=$3 } END { for (p in a) { if (a[p] == "install") { print p } } }' /var/log/dpkg.log | sort -u > installed 

然后,我将initialinstalled的两个文件进行比较,仅列出installed唯一项目。

 comm -23 installed initial > custom 

从那里我想过滤掉依赖项,这是这个方法可能会错过一些所需的包的地方,它不知道也明确安装的依赖项。

我写了一个快速bash函数来缩短处理这些项目的步骤。

 function rdep() { apt-cache rdepends $1 | tail -n +3 | sed -e 's/^ //' -e '/^ /d' | cut -d':' -f1 | sort -u; } 

之后,我使用xargs将每行从我的文件custom传递到此函数。

 echo "$(for i in $(cat custom) ; do rdep $i ; done)" | sort -u > deps 

一旦我得到了每个可能的依赖项的长列表(不确定每个可能的语句),我再次获得了单个文件所特有的行。

 comm -23 custom deps > manual 

我完成的软件包列表现在位于一个名为manual的文件中供我查看。

有人链接到https://unix.stackexchange.com/questions/3595/ubuntu-list-explicitly-installed-packages/3624#3624这确实有一个很好的解决方案,但是,它作为aptitude的输出行为不正确已经改变。 这是一个更新版本,基于当前安装的软件包与12.04 LTS相比较。 您将需要安装aptitude ,这是唯一的要求。

 aptitude search '~i !~M' -F '%p' | sort -u | tr -d ' ' > currentlyinstalled && wget -qO - http://mirror.pnl.gov/releases/precise/ubuntu-12.04.3-desktop-amd64.manifest | cut -f 1 | sort -u > defaultinstalled && comm -23 currentlyinstalled defaultinstalled 

要将上述命令分解为多个部分,该位将为系统上安装的所有内容每行输出一个包

 aptitude search '~i !~M' -F '%p' | sort -u | tr -d ' ' > currentlyinstalled 

这将下载默认包列表并裁剪冗余信息。

 wget -qO - http://mirror.pnl.gov/releases/precise/ubuntu-12.04.3-desktop-amd64.manifest | cut -f 1 | sort -u > defaultinstalled 

comm比较两个文件并输出默认列表中不包含的包。

 comm -23 currentlyinstalled defaultinstalled 

使用分发清单文件作为基本包集。 按体系结构和部分将手动安装的结果排序到包组中,因此更容易关注包组(可能您不关心某些部分)。

https://gist.github.com/darrenleeweber/8cc570ff402f19af7fa4

 #!/bin/bash manifest_url='http://releases.ubuntu.com/releases/trusty/ubuntu-14.04.3-desktop-amd64.manifest' manifest_file=$(echo $manifest_url | sed -e 's#.*/##g') if [ ! -e $manifest_file ]; then wget -q $manifest_url fi cat $manifest_file | cut -f1 | sort -u > default_installed.txt aptitude search '~i !~M' -F '%p' --disable-columns | sort -u > currently_installed.txt comm -23 currently_installed.txt default_installed.txt > manually_installed.txt # sort the 'mannually_installed.txt' packages by architecture and section mkdir -p package_files while read p; do apt-cache show $p > info.txt arch=$(grep -m1 'Architecture: ' info.txt | sed -e 's/Architecture: //') section=$(grep -m1 'Section: ' info.txt | sed -e 's/Section: //' -e 's/\//_/g') file="${arch}_${section}_packages.txt" echo $p >> "package_files/$file" done  
 #! /bin/sh DEFAULT=`tempfile` CURRENT=`tempfile` cat /var/log/installer/initial-status.gz | gzip -d | grep '^Package:' | awk '{ print $2}' | sort -u > $DEFAULT aptitude search '~i !~M' -F '%p' | sort -u | tr -d ' ' | awk '{ print $1}' > $CURRENT comm -23 $CURRENT $DEFAULT rm $DEFAULT rm $CURRENT 

我找不到一个适合我的,所以我写了一个剧本。 通过分析/var/log/apt/history.log*和/ var / log / aptitude的内容,然后按datetime排序,产生两个列表,一个是手动安装的pkgs,另一个是安装但是删除了pkgs。 带有“apt list”validation的脚本。 有点偏差,因为使用dpkg安装并修改了PPA源码。

我放在这里, https://github.com/eexpress/eexp-bin/blob/master/self-installed-pkg.pl 。

如果有人需要测试它,可能需要修改一些代码,因为我的日志文件是用中文和英文混合的(特别是RFC2822日期时间格式),我需要处理它。 在此处输入图像描述

我想你想使用/var/log/apt/history.log及其朋友来进行所做的更改:

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

(从源代码修改)

将使用apt-get install的变体为您提供已在命令行安装的所有软件包。

它获取旧history.log的压缩文件history.log将它们与当前的history.log一起添加并通过grep,使用apt [-get] install [和/或重新安装]提取行并显示行的其余部分(-o flag)相当于包名。

如果你只想在不同的行上包名,那么这需要一点修改(例如用sed ); 为读者练习!

值得注意的是,“状态”部分中的突触包管理器( gksu synaptickdesudo synaptic )具有“已安装(手动)”列表。 如果您标记要删除的整个列表[不要应用它!!],您应该能够保存标记的更改并以此方式获取包列表。 警告:这为我锁定了synaptic (大概计算依赖删除)。