如何找到手动安装的包?
我在我的计算机上安装了一个普通的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
然后,我将initial
和installed
的两个文件进行比较,仅列出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 synaptic
或kdesudo synaptic
)具有“已安装(手动)”列表。 如果您标记要删除的整个列表[不要应用它!!],您应该能够保存标记的更改并以此方式获取包列表。 警告:这为我锁定了synaptic
(大概计算依赖删除)。