我想获取由apt
或手动安装的软件包的列表,aptitude
并能够确定foobar
软件包是手动安装还是自动安装。在命令行中有什么整齐的方法吗?
我想获取由apt
或手动安装的软件包的列表,aptitude
并能够确定foobar
软件包是手动安装还是自动安装。在命令行中有什么整齐的方法吗?
Answers:
您可以使用这两个单线之一。两者在我的机器上都能产生完全相同的输出,并且比到目前为止(在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
在行尾去除空白区域。其他可能性也不起作用:
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帖子作为参考,但是以上解决方案均无效:
两者都列出了比上述解决方案更多的软件包。
编辑:如果您已从以前的版本升级,该怎么办:
如果已将Ubuntu从一个版本升级到另一个版本,则可能需要调整此过程。在这种情况下,除了当前版本的initial-status.gz文件之外,我还将检查较新版本的清单文件(请参见上文)。您只需添加另一个比较即可轻松做到这一点。只使用清单文件是行不通的,因为清单文件不幸地不包含initial_status.gz文件所做的所有事情(我检查过)。
/var/log/installer/initial-status.gz
丢失了。我也想知道这是否取决于apt标记manual
?
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中(示例:xserver-xorg,ubuntu-desktop)。感觉您的列表会更有用,但是在不知道这些差异来自何处的情况下,很难决定...(但我敢肯定,我是手动安装了nginx和lightdm的...)[抱歉,我刚刚写了同样;)]
在apt软件包的较新版本中,还有apt-mark命令
apt-mark showmanual
linux-image-3.11.0-*-generic
等视为手册
linux-image-3.13.0-24-generic
是手动的,但当前linux-image-3.13.0-27-generic
是自动的。似乎是引用包的升级(在这种情况下linux-image-generic
,它更改了依赖性),手动标记已自动设置
apt-get autoremove
。这绝对不是您想要的。
对于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桌面应用中获取安装。
apt-mark showauto | grep -iE '^foobar$'
如果该软件包是自动安装的,则将输出“ foobar”,否则不输出。
aptitude search '!~M ~i'
将列出未自动安装的软件包。可惜的是,从10.10开始,Ubuntu Desktop的默认安装中没有包含此功能。
aptitude search
显示所有软件包,而不仅仅是手动安装的软件包(我假设这就是OP想要的软件包)
aptitude search '!~M ~i'
,它列出了1043个程序包。我没有办法手动安装这么多软件包。
以下脚本将打印出所有未设置为自动安装并因此手动安装的软件包:
#!/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打印自动安装的软件包的方式。
sys.exit(1)
no import sys
可能会导致新版本的python中出现错误。要么import sys
使用exit(1)
。
正如一些人所评论的那样,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.exit(1)
no import sys
可能会导致新版本的python中出现错误。要么import sys
使用exit(1)
。
如果没有人使用apr-something命令给您一个很好的答案,则可以采用困难的方式。Apt-get将其信息存储在/ var / lib / apt / extended_states中。自动安装的所有文件都将添加到该文件中。如果您手动在该文件中安装了软件包,则该软件包将保留在该文件中,但在第二行中自动安装:0。它没有被删除。
注意:如预期的那样,如果出现文件位置更改,更好的答案可能会起作用。我保留我的名称,以防文件位置上的信息有用。
apt-get install liferea
,但没有安装,但是我得到的输出相当于“标记为手动安装”。现在liferea仍在文件中,除了下一行用0
代替1
。另外,您应该将regex模式更改为" foobar$"
而不是foobar
。
经过大量搜索之后,我设法组装了此脚本。它对我来说很好:
# 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,这样更快。
apt-mark
可能会显示某些软件包的体系结构,但不会显示dpkg -l
。
apt-cache search
是慢的。使用诸如help.ubuntu.com/community/ListInstalledPackagesByDate之类的东西提前获取安装日期的列表可能会更有效
正如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)
为了便于阅读,我将其分为两行。这是做什么的?
apt-mark
comm -3 <(dpkg -l | grep '^ii' | cut -d \ -f 3|sort) <(apt-mark showauto|sort)
会更好;)
这将列出所有手动安装的软件包,不包括:依赖项,已卸载的软件包,在系统安装期间安装的软件包。
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
}