生成手动安装的包列表并查询各个包

我想获得aptaptitude手动安装的软件包列表,并能够找出手动或自动安装foobar软件包。 从命令行有没有任何巧妙的方法?

您可以使用这两个单行中的任何一个。 两者在我的机器上产生完全相同的输出,并且比在此问题中直到现在(2014年7月6日)提出的所有解决方案更精确。

使用apt-mark

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

使用aptitude

 comm -23 <(aptitude search '~i !~M' -F '%p' | sed "s/ *$//" | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort -u) 

虽然我怀疑这些软件包实际上是由安装后通过语言本地化设置安装的,或者例如通过Totem编解码器安装程序安装,但很少有软件包仍然存在。 此外,linux-header版本似乎也在积累,即使我只安装了非特定于版本的元数据包。 例子:

 libreoffice-help-en-gb openoffice.org-hyphenation gstreamer0.10-fluendo-mp3 linux-headers-3.13.0-29 

它是如何工作的:

  1. 获取手动安装的包列表。 对于aptitude,额外的sed剥离了行尾的剩余空格。
  2. 在全新安装后立即获取安装的软件包列表。
  3. 比较文件,仅输出文件1中不存在于文件2中的行。

其他可能性也不起作用:

  • 使用ubuntu-14.04-desktop-amd64.manifest文件( 此处为Ubuntu 14.04)而不是/var/log/installer/initial-status.gz 。 更多包显示为手动安装,即使它们不是。
  • 使用apt-mark showauto而不是/var/log/installer/initial-status.gz 。 例如, apt-mark不包含xserver-xorg包,而另一个文件包含xserver-xorg包。

我使用了各种其他StackExchangepost作为参考,但是没有一个像上面的解决方案一样好用:

  • 能力+表现
  • initial-status.gz + apt-mark showauto

两者都列出了比上述解决方案更多的包。

编辑:如果您从以前的版本升级,该怎么办:

如果您已将Ubuntu从一个版本升级到下一个版本,则可能需要调整此过程。 在这种情况下,除了当前版本的initial-status.gz文件之外,我还会检查较新版本的清单文件(参见上文)。 您可以通过添加另一个比较轻松地做到这一点。 仅使用清单文件将不起作用,因为清单文件遗憾地不包含initial_status.gz文件所做的所有事情(我已检查过)。

在apt的较新版本中,还有apt-mark命令

 apt-mark showmanual 

apt-mark showauto | grep -iE '^foobar$' apt-mark showauto | grep -iE '^foobar$'将输出“foobar”如果包是自动安装的,否则没有。

aptitude search '!~M ~i'将列出未自动安装的软件包。 从10.10开始,这可能不会成为Ubuntu桌面上默认安装的一部分。

对于Ubuntu 16.04,请查看日志文件/var/log/apt/history.log

例如:

 zgrep 'Commandline: apt' /var/log/apt/history.log /var/log/apt/history.log.*.gz 

它并不完美,但它非常擅长清楚地说明我手工安装的内容。 在-B 1上放一个-B 1以查看它何时安装。

示例输出

 Commandline: apt install postgresql-9.5-plv8 Commandline: aptdaemon role='role-install-file' sender=':1.85' Commandline: apt install task Commandline: apt autoremove Commandline: apt install atom Commandline: apt upgrade Commandline: apt-get install asciinema Commandline: apt install iperf3 Commandline: apt upgrade Commandline: apt-get install chromium-browser Commandline: apt install joe cpanminus build-essential postgresql libdbd-pg-perl libcrypt-openssl-bignum-perl libcrypt-openssl-rsa-perl libio-socket-ssl-perl libnet-ssleay-perl libssl-dev Commandline: aptdaemon role='role-commit-packages' sender=':1.2314' Commandline: apt install git Commandline: apt install sqlite Commandline: apt install whois Commandline: apt install libdbd-pg-perl Commandline: apt install perl-doc Commandline: apt upgrade 

不确定这是否会提升aptitude 。 它似乎没有从Ubuntu软件桌面应用程序中获取安装。

以下脚本将打印出未设置为自动安装的所有软件包,因此需要手动安装:

 #!/usr/bin/python try: import apt_pkg except ImportError: print "Error importing apt_pkg, is python-apt installed?" sys.exit(1) apt_pkg.init() STATE_FILE = apt_pkg.config.find_dir("Dir::State") + "extended_states" auto = set() tagfile = apt_pkg.TagFile(open(STATE_FILE)) while tagfile.step(): pkgname = tagfile.section.get("Package") autoInst = tagfile.section.get("Auto-Installed") if not int(autoInst): auto.add(pkgname) print "\n".join(sorted(auto)) 

它基于apt-mark如何打印自动安装的包。

有几个人评论说,apt-mark showmanual似乎有点儿麻烦(我把它报告为bug 727799 )。 当我使用它时,它实际上报告了许多甚至没有记录在/ var / lib / apt / extended_states(这应该存储在那里)的东西,并且apt-get没有记录安装的内容/ var / lib / apt / extended_states(仅在/ var / lib / dpkg / status中)。 上面的txwikinger的python脚本直接从/ var / lib / apt / extended_states中提取,但如果你今天使用它,语法可能不起作用(我刚开始用Kubuntu 13.10生成错误)。 更新的语法是:

 #!/usr/bin/python import sys try: import apt_pkg except ImportError: print "Error importing apt_pkg, is python-apt installed?" sys.exit(1) apt_pkg.init() STATE_FILE = apt_pkg.config.find_dir("Dir::State") + "extended_states" auto = set() tagfile = apt_pkg.TagFile(open(STATE_FILE)) while tagfile.step(): pkgname = tagfile.section.get("Package") autoInst = tagfile.section.get("Auto-Installed") if not int(autoInst): auto.add(pkgname) print "\n".join(sorted(auto)) 

对我来说,这是一个非常短的5个项目列表,似乎也不准确。

要获取所有软件包的列表(未安装,由用户安装或默认安装,跨所有PPA), apt采用以下方法:

apt list [option]

对此有用的可能选项包括:

--installed只显示系统上安装的软件包(大约50,000+)

--manual-installed列出直接或作为依赖项由命令显式安装的软件包。

或者,您可以这样做:

apt list --manual-installed | grep -F \[installed\] apt list --manual-installed | grep -F \[installed\]获取仅由用户命令及其依赖项产生的软件包列表,并获取有关它们的其他信息,例如支持的版本和体系结构(x86,x86_64,amd64,all等)

正如Li Lo所说, apt-mark showauto应该会为你提供一个自动安装的东西。

现在为了展示手动安装的东西,事实certificate,aptitude有一个可爱的简单搜索修改器。 但你不想这样做。 你想写一个巨大的bash命令来做一些火箭科学。

注意:这更像是一个很酷的例子,你会看到对你所有朋友的大量重击命令。

 comm -3 <(dpkg-query --show -f '${Package} ${Status}\n' | \n grep "install ok installed" | cut --delimiter=' ' -f 1) <(apt-mark showauto) 

为了便于阅读,我把它分成两行。 这是做什么的?

  • 首先,我们查询dpkg以获取已安装的软件包列表。
  • 我们过滤那些实际安装的(不只是残留配置)
  • 我们砍掉了地位
  • 我们将该列表与apt-mark的自动列表进行比较
  • 我们摇滚乐,因为我们可以。

如果没有人使用apr-something命令给你一个很好的答案,你可以用艰难的方式去做。 Apt-get将其信息存储在/ var / lib / apt / extended_states中。 自动安装的任何文件都将添加到此文件中。 如果您手动在此文件中安装了一个软件包,该软件包将保留在此文件中,但在第二行中使用自动安装:0。 它没有被删除。

注意:正如预期的那样,如果出现文件位置更改,可能会有更好的答案。 我保留我的以防万一文件位置的信息很有用。

经过谷歌搜索后,我成功地组装了这个脚本。 它适合我:

 # List of all packages currently installed current=$(dpkg -l | awk '{print $2}' | sort | uniq) # List of all packages that were installed with the system pre=$(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort | uniq) # List of packages that don't depend on any other package manual=$(apt-mark showmanual | sort | uniq) # (Current - Pre) ∩ (Manual) packages=$(comm -12 <(comm -23 <(echo "$current") <(echo "$pre")) <(echo "$manual") ) for pack in $packages; do packname=$(echo $pack | cut -f 1 -d ":") desc=$(apt-cache search "^$packname$" | sed -E 's/.* - (.*)/\1/') date=$(date -r /var/lib/dpkg/info/$pack.list) echo "# $desc" echo "# $date" echo "sudo apt-get install $pack" echo -e "" done 

我想提供一个GUI解决方案。

在此处输入图像描述

  1. 打开Synaptic Package Manager

  2. 转到Status

  3. 单击Installed (manual)

它将给出apt或aptitude手动安装的软件包列表。

不幸的是,我在Custom Filters找不到任何选项,以确定是手动安装还是自动安装foobar包。

如果软件包在“ Installed下但未在“ Installed (manual)则它将自动安装。 如果软件包在Installed (manual)则手动安装。

这将列出所有手动安装的软件包,但不包括:依赖项,已卸载的软件包,系统安装期间安装的软件包。

 unopts() { in=`cat` echo "$in" | sed -r 's/ --[^ ]+//g;s/ -[^ ]+//g' } list() { cat '/var/log/apt/history.log' | grep --color=never -v '\-o APT::Status-Fd=4 \-o APT::Keep-Fds::=5 \-o APT::Keep-Fds::=6' | egrep --color=never "Commandline: apt-get.* $1" | sed -r "s/Commandline: apt-get//;s/ $1//" | unopts | tr ' ' '\n' | sed '/^$/d' } hapt() { tmp=`mktemp -d` installed=$tmp/installed deleted=$tmp/deleted dpkg=$tmp/dpkg list 'install' > $installed list '(remove|purge|autoremove)' > $deleted dpkg --get-selections | grep -v 'deinstall' | cut -f 1 > $dpkg while read package do sed -i "0,/$package/{//d;}" $installed done < $deleted while read package do if [ -z "`grep --color=never "^$package$" $dpkg`" ] then sed -i "0,/$package/{//d;}" $installed fi done < $installed cat $installed rm -r $tmp }