生成手动安装的软件包列表并查询单个软件包


183

我想获取由apt或手动安装的软件包的列表,aptitude并能够确定foobar软件包是手动安装还是自动安装。在命令行中有什么整齐的方法吗?


请参阅unix.stackexchange.com上的此答案以获取可过滤掉库存包装的解决方案。
德克·伯格斯特罗姆

可能重复吗?- askubuntu.com/questions/365
JRG


真正好的解决方案,它不包括默认安装的软件包
pcworld,

在这里仔细回答答案。人们并没有说更多的软件包出现,但是他们忘记了手动安装的依赖软件包。
安德烈·菲盖雷多

Answers:


206

您可以使用这两个单线之一。两者在我的机器上都能产生完全相同的输出,并且比到目前为止(在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)

只有极少数的包还是漏掉,虽然我怀疑这真正由用户安装,或者直接通过语言本地化安装程序在安装后,或例如,通过编解码器图腾安装。另外,即使我仅安装了非特定于版本的metapackage,Linux标头版本也似乎在累积。例子:

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

它是如何工作的:

  1. 获取手动安装的软件包的列表。为了适应性强,附加功能会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.gzapt-mark例如,不包含xserver-xorg软件包,而另一个文件包含。

我使用了其他各种StackExchange帖子作为参考,但是以上解决方案均无效:

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

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

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


7
这对我不起作用,因为/var/log/installer/initial-status.gz丢失了。我也想知道这是否取决于apt标记manual
安华

1
las,没有服务器版本的清单。
Antti Haapala'4

我运行了showmanual命令(如下)。并用于comm比较两个(排序的)列表。该showmanual结果给了我1,840 多个从独特的包装apt-mark showmanual不采用这种方法表示。此comm命令的输出没有唯一的软件包。我认为记录下来更有趣,对于我的PC,两个结果中都列出了894个软件包。不知道为什么会有如此巨大的差异。一些(很多?)软件包似乎是特定于发行版的。其他诸如XOrg,GTK组件之类的lib*东西可能会进行更新。 无论如何,这个答案是一个很好的开始。

我只是将您的解决方案与进行了比较apt-mark showmanual。有趣的是有多少差异可见。您的列表中有238个程序包,而showmanual返回了1717个程序包。在安装的2179个软件包中,两个列表中只有223个,只有15个位于您的列表中(示例:nodejs,lightdm),而223个仅包含在showmanual中(示例:xser​​ver-xorg,ubuntu-desktop)。感觉您的列表会更有用,但是在不知道这些差异来自何处的情况下,很难决定...(但我敢肯定,我是手动安装了nginx和lightdm的...)[抱歉,我刚刚写了同样;)]
丹尼尔·奥尔德

64

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

apt-mark showmanual

35
这显示出比我手动安装的软件包更多的软件包。
Umang 2014年

1
@Umang你是对的。我写这个答案时会说不是这样。我的系统上没有理由将linux-image-3.11.0-*-generic等视为手册
Daniel Alder 2014年

1
@Umang也许这会帮助您askubuntu.com/questions/432743/…,但答案不被接受。事实是,许多全新安装的软件包已被标记为手动。但是仍然有些奇怪的事情。与我的示例保持一致:linux-image-3.13.0-24-generic是手动的,但当前linux-image-3.13.0-27-generic是自动的。似乎是引用包的升级(在这种情况下linux-image-generic,它更改了依赖性),手动标记已自动设置
Daniel Alder 2014年

5
@DanielAlder全新安装的某些软件包应标记为手册。如果没有软件包标记为手动,则可以使用删除整个系统apt-get autoremove。这绝对不是您想要的。
安东·K

2
如果“手动安装”是指“由用户在初次安装OS后安装”,则此答案不正确。
Seamus

21

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

例如:

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

它不是完美的,但是在弄清楚我手动安装的内容方面还是相当不错的。-B 1在grep上放一个,以查看其安装时间。

输出示例

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 Software桌面应用中获取安装。


1
多年来的所有答案中,这是唯一一个在18.04服务器中甚至可以接近的答案。
Quentin Skousen

20

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

aptitude search '!~M ~i'将列出未自动安装的软件包。可惜的是,从10.10开始,Ubuntu Desktop的默认安装中没有包含此功能。


aptitude search显示所有软件包,而不仅仅是手动安装的软件包(我假设这就是OP想要的软件包)
Oli

1
@Oli:研究智能搜索模式;我在那里使用的模式应该完全符合OP的要求。
李罗

了 它显示了未安装的软件包的全部负载。
奥利(Oli)

7
事情不对劲,我正在使用aptitude search '!~M ~i',它列出了1043个程序包。我没有办法手动安装这么多软件包。
ThatGraemeGuy 2010年

这绝对不能按要求工作,并且还会打印预安装的软件包。
Irfy 2012年

9

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

#!/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打印自动安装的软件包的方式。


先生,您好!与公认的答案相反,这实际上有效。
Irfy 2012年

只给我展示几个包裹---肯定很多。
Rmano 2014年

同样在这里,肯定是在我安装它们后立即丢失了手动安装的软件包。
David Ljung麦迪逊,

使用sys.exit(1)no import sys可能会导致新版本的python中出现错误。要么import sys使用exit(1)
Videonauth

7

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

apt list [option]

可能有用的选项是:

--installed 仅显示系统上已安装的软件包(约50,000多个)

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

或者,您可以执行以下操作:

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


5

正如一些人所评论的那样,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个项目的简短清单,似乎也不是很准确。


1
使用sys.exit(1)no import sys可能会导致新版本的python中出现错误。要么import sys使用exit(1)
Videonauth

4

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

在此处输入图片说明

  1. 打开 Synaptic Package Manager

  2. Status

  3. 请点击 Installed (manual)

它将提供通过apt或aptitude手动安装的软件包的列表。

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

如果软件包在下面,Installed但不在下面,Installed (manual)则表示它是自动安装的。如果软件包在下面,Installed (manual)则说明它是手动安装的。


2

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

注意:如预期的那样,如果出现文件位置更改,更好的答案可能会起作用。我保留我的名称,以防文件位置上的信息有用。


1
否。我快速浏览了该文件,发现liferea被标记为自动安装。我做了一个apt-get install liferea,但没有安装,但是我得到的输出相当于“标记为手动安装”。现在liferea仍在文件中,除了下一行用0代替1。另外,您应该将regex模式更改为" foobar$"而不是foobar
乌曼格2010年

确实如此。我的错,在我的系统中没有0线,但这种情况很少发生。我更新答案以防万一。
哈维尔·里维拉

2

经过大量搜索之后,我设法组装了此脚本。它对我来说很好:

# 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

您可以使用sort -u代替sort | unique。与apt-mark未显示的体系结构一样,您应该在设置操作(或使用dpkg-query -W -f='${Package}\n')之前从dpkg的输出中删除它。此外,dpkg可能会列出一些当前未安装的软件包。至于“ desc”,您可以使用`dpkg-query -W -f ='#$ {binary:Summary} \ n'$ pack,这样更快。
jarno 2015年

哦,apt-mark可能会显示某些软件包的体系结构,但不会显示dpkg -l
jarno 2015年

apt-cache search是慢的。使用诸如help.ubuntu.com/community/ListInstalledPackagesByDate之类的东西提前获取安装日期的列表可能会更有效
opticyclic

1

正如Li Lo所说,apt-mark showauto应该为您自动安装的东西提供一个繁琐的清单。

现在,要显示手动安装的东西,事实证明,有一个漂亮的简单搜索修饰符可用于智能。但是您不想这样做。您想编写一个执行某些火箭科学的巨大bash命令。

注意:这更多地说明了您向所有朋友发出大量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
  • 因为我们可以,所以我们摇摆不定。

我怀疑这是否正确,因为dpkg通常会显示未安装的软件包
txwikinger 2010年

我知道你的意思,但我的bash-fu不够强壮。我知道您可以显示来自dpkg-query的状态,向下进行grep,然后切下该状态。我去吧
奥利(Oli)

comm -3 <(dpkg -l | grep '^ii' | cut -d \ -f 3|sort) <(apt-mark showauto|sort)会更好;)
LassePoulsen

-1

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

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
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.