我想获取由aptaptitude手动安装的软件包列表,并能够找出是手动还是自动安装了foobar软件包。在命令行中有什么整洁的方法吗?

评论

请参阅unix.stackexchange.com上的此答案以获取可过滤掉库存包装的解决方案。

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

是否可能会告诉我我安装的不是香草安装的那些软件包?

真正好的解决方案,它不包括默认安装的软件包:Ubuntu列出了明确安装的软件包

请在此处仔细回答答案。人们没有说更多的软件包出现的方式,但是他们忘记了手动安装的依赖软件包。

#1 楼

您可以使用这两个单线之一。两者都在我的机器上产生完全相同的输出,并且比迄今为止在此问题中提出的所有解决方案(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    


如何工作:


获取手动安装的软件包的列表。为了适应性,附加的sed在行的末尾去除了剩余的空格。
在全新安装后立即获取已安装的软件包的列表。
比较文件,仅输出文件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软件包,而另一个文件包含。

我使用了其他各种StackExchange帖子作为参考,但是上述解决方案都不起作用:


aptitude + manifest
initial-status.gz + apt-mark showauto

两者都列出了比上述解决方案更多的软件包。编辑:如果您已从以前的版本升级,该怎么办:

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

评论


这对我不起作用,因为缺少/var/log/installer/initial-status.gz。我也想知道这是否取决于手册的apts标记?

–安瓦尔
16-10-29在8:20

las,没有服务器版本的清单。

–安蒂·哈帕拉(Antti Haapala)
17-4-10在13:22



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

–将
18年6月24日在12:45

今天我了解了“ comm -23”!感谢那!

– David Ljung麦迪逊·斯特拉尔
20年1月29日在20:08

清单文件可以从releases.ubuntu.com下载

–黑暗龙
20年4月6日在21:34

#2 楼

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

apt-mark showmanual


评论


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

– Umang
2014年7月7日在11:05

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

–丹尼尔·奥尔德(Daniel Alder)
2014年7月8日在11:23



@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年7月8日在11:42



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

–安东K
16 Dec 2'在10:57



如果“手动安装”表示“由用户在初始安装OS后安装”,则这不是正确的答案。

– Seamus
19年4月6日在16:37

#3 楼

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

评论


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

– Quentin Skousen
19年2月6日在16:48

不要忘记日志会不时被删除...

–丹尼尔·奥尔德(Daniel Alder)
19-10-23在8:19

#4 楼

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

aptitude search '!~M ~i'将列出未自动安装的软件包。遗憾的是,从10.10开始,Ubuntu桌面默认安装中不会包含此功能。

评论


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

–奥利♦
10年8月16日在17:42

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

– Li Lo
10年8月16日在17:44

我跑了它显示了未安装的软件包的全部负载。

–奥利♦
10年8月16日在17:46

事情不对劲,我正在使用智能搜索'!〜M〜i',它列出了1043个软件包。我没有办法手动安装这么多软件包。

– ThatGraemeGuy
2010-09-16 7:42

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

– Irfy
2012年11月1日,下午2:55

#5 楼

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

apt list [option]

可能的选项有用的方法是:

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

--manual-installed列出由明确安装的软件包

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

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

#6 楼

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

#!/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年11月1日在2:53

只给我看几个包裹---肯定很多。

–罗马诺
2014年1月23日在17:36

同样,在我安装它们之后,肯定会丢失手动安装的软件包。

– David Ljung麦迪逊·斯特拉尔
16 Mar 2 '16 at 1:23

在不导入sys的情况下使用sys.exit(1)可能会在较新版本的python中导致错误。导入sys或使用exit(1)。

– Videonauth
17年11月26日14:40



#7 楼

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

评论


在不导入sys的情况下使用sys.exit(1)可能会在较新版本的python中导致错误。导入sys或使用exit(1)。

– Videonauth
17年11月26日14:40



#8 楼

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




打开Synaptic Package Manager
转到Status
单击Installed (manual)

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

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

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

#9 楼

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

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

评论


否。我快速浏览了该文件,发现liferea被标记为自动安装。我做了一个apt-get install liferea,但没有安装,但是我得到的输出具有“标记为手动安装”的效果。现在,liferea仍在文件中,除了下一行的0而不是1。此外,您还应将正则表达式模式更改为“ foobar $”,而不仅仅是foobar。

– Umang
2010年8月17日在13:21



确实如此。我的错,在我的系统中没有0线,但是这应该很少发生。我更新答案以防万一。

–哈维尔·里维拉(Javier Rivera)
2010年8月17日在16:14



#10 楼

经过大量搜索之后,我设法组装了此脚本。它适合我:

# List of all packages currently installed
current=$(dpkg -l | awk '{print }' | 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/.* - (.*)//')
    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 |独特。由于apt-mark不显示体系结构,因此应在设置操作之前从dpkg的输出中删除它(或使用dpkg-query -W -f ='$ {Package} \ n')。此外,dpkg可能会列出一些当前未安装的软件包。至于“ desc”,您可以使用`dpkg-query -W -f ='#$ {binary:Summary} \ n'$ pack,这样更快。

– jarno
2015年12月20日15:54

哦,apt-mark可以显示某些软件包的体系结构,但不能显示dpkg -l的体系结构。

– jarno
2015年12月20日23:47

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

–opticyclic
17年8月24日在3:37

#11 楼

正如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
10年8月16日在17:47

我知道你的意思,但我的拳头不够强。我知道您可以显示来自dpkg-query的状态,向下grep,然后切下状态。我去吧

–奥利♦
10年8月16日在17:49



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

–拉瑟·波尔森
10年8月16日在17:54



#12 楼

@jmiserez的答案的更新版本:
 comm -23 \
    <(apt-mark showmanual | sort -u) \
    <(grep -oP '^(?:Package|Depends):\s+\K.*' /var/log/installer/status \
        | grep -oP '[^\s,()]+?(?=(?:\s+\([^)]+\))?+(?:,|$))' \
        | sort -u)
 

日志不再存储在/var/log/installer/initial-status.gz上,原始记录不遗漏包。它产生的列表将包括您没有手动安装的软件包,但是长度更易于管理,仍然非常有用。

#13 楼

不确定这是否有帮助,但是要查找当前用户最近手动安装的软件包,请搜索历史记录。例如,对于bash

 $ history | egrep '\bapt\b'
 


修改grep以检查特定的软件包。

#14 楼

如果使用apt从终端安装了所有软件包,则可以在apt install *的内容上抛出一个简单的正则表达式搜索/var/log/apt/history.log,然后看看它吞噬了什么。
正则表达式可能很简单:Commandline: apt install [\w -]+(在日志之后) Ubuntu 16.04上apt的语法)

#15 楼

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

 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.* " |
  sed -r "s/Commandline: apt-get//;s/ //" |
  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
}