如何查找手动安装的软件包?


48

我在计算机上安装了普通的Ubuntu 10.10,并通过apt-get安装了一些软件。上周,我设法破坏了一切,并从头开始,并且需要重新安装软件。有什么方法可以创建包含我手动安装的所有软件包的列表?

这样就可以给我一个像清单,texlive, ...而不是清单texlive, texlive-dep1, textlive-dep2, ...删除所有标准软件包?

如果我能以某种方式找出我从常规安装中删除了哪些程序,那也将很棒!


更新2015-05-23:我现在在系统上使用Ansible作为配置管理。我在那里指定要安装的软件包。这达到了目标,甚至可以更好地将所有程序安装在新系统上。因此,这个问题可能是进入一些轻型配置管理的入口。

Answers:


24

有了这个建议,我假设您的旧安装仍然可以启动!

要将一组软件包复制到另一台计算机上:

在系统A上,运行:

dpkg --get-selections | grep -v deinstall > my-selections

my-selections文件移到系统B。

在系统B上,运行:

dpkg --set-selections < my-selections

接着:

sudo apt-get dselect-upgrade

重要说明:如果您从非标准存储库和/或PPA安装了软件包,则还需要复制/etc/apt/sources.list/etc/apt/sources.list.d/在运行升级之前 System A从System A。

您也可以dpkg用来查看已删除的内容(注意:这还将包括您手动安装删除的软件包):

dpkg --get-selections | grep deinstall

您可以在终端中查看结果,或者当然可以重定向到文件。


9
我想获得所有软件包的列表,但是我只想知道我明确安装的软件包的名称。所以公正,something而不是something-common那么好。
Martin Ueding 2011年

6
是的,虽然这很有用,但它并不能解决问题。
Timmmm 2012年

3
如果这样做,则删除程序时将永远不会清除自动安装的依赖项。为什么人们会投票否决要求提问者明确要求的答案?
jbo5112

20

来自superuser.com的该线程提供了以下解决方案:

aptitude search '?installed ?not(?automatic)'

2
这对我不起作用。仅列出所有已安装的内容,或者列出比我明确要求的更多的内容。
Timmmm 2012年

它列出了您已安装的所有内容apt-get以及它们的依赖关系。因此,例如,如果您安装了aptitude,则它还会列出apt-xapian-index aptitude-common libboost-iostreams1.54.0 libclass-accessor-perl libcwidget3 libept1.4.12 libio-string-perl libparse-debianchangelog-perl libsigc++-2.0-0c2a libsub-name-perl libtimedate-perl libxapian22 python-chardet python-debian python-six python-xapian
Runemoro

10

如果您的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

6

您可以使用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
...

我通过配置debfoster /etc/debfoster.conf将此列表放在/etc/debfoster-keepers并使用etckeeper跟踪文件以保留历史记录和备份。此处答案显示了如何从换行符分隔的文本文件中安装软件包列表:

sudo apt-mark manual $(cat debfoster-keepers)

请注意此处的限制,清除的软件包前面带有“-”。因此,您想在调用apt-mark之前删除这些行。

即使debfoster的网站上说debfoster不再支持智能,我还是喜欢debfoster的快速简单的配置。它使您进入程序包数据库的中间,使您可以清理内容,从而使自动手动程序包更加明显。

在debfoster提示符下键入“ h”以解释您的选择。输入“?” 查看包装说明。该如何到这里可能是有用的。


5
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



2

我终于明白了:

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"

2
我猜这仅在您仅使用aptitude安装软件包时才有效。虽然有类似的文件/var/log/apt/history.log(.N.gz)
Timmmm 2012年

您可以使用zgrep代替gunzip或通过zcat管道传递到grep。我相信这是gzip随附的包装器脚本。它还接受未压缩的文件,因此您可以将脚本简化为zgrep -E '(\[INSTALLIEREN\]|\[INSTALL\])' /var/log/aptitude* | awk '{ print $2 }'
Steve Buzonas 2015年

2

我可以通过打开/ var / log / apt /中的日志文件来提取所有内容

然后,我进入并手动过滤掉apt-get安装软件包。可能有一种方法可以通过编程方式执行此操作,但我不知道。


1
cd /var/log/apt
cat  history.log | grep Commandline

这样,您可以查看过去执行的命令列表。

如果您需要更多信息,请删除grep代码:

less history.log

如果日志已压缩(即以gz结尾)

gunzip <filename>

完成后再次压缩它,您可以执行以下操作:

gzip <filename>

1
为什么不使用解压缩而不是重新压缩日志文件zcat?就像一样简单zcat filename.gz。只需将其用于gzip压缩文件即可代替cat。也grep可以替换zgrep,例如zgrep Commandline history.log.1.gz
lgarzo

根据您的想法,我提出了一个命令行:(grep "Commandline" history.log ; zgrep "Commandline" history.log.*.gz ) | grep " install " | grep -v -- "--yes" | sed -r "s/^.*install //"。它具有缺陷,因为还会列出已删除的软件包,并且如果一个软件包安装了多次,则会列出多次。
lgarzo

1

我没有找到任何适用于我的解决方案,我已经用dpkg安装了很多deb软件包,而我特别寻找的一些项目却丢失了。

一个相当长的衬纸,但可以方便地复制和粘贴:

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

然后,我比较了两个文件initialinstalled仅列出了安装所特有的项目。

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; }

之后,我使用将从文件的每一行传递custom到此函数xargs

echo "$(for i in $(cat custom) ; do rdep $i ; done)" | sort -u > deps

一旦获得了所有可能依赖项的详细清单(不确定每个可能的语句),我再次获得了单个文件所独有的行。

comm -23 custom deps > manual

现在,我已完成的软件包列表在一个名为manual供我查看的文件中。


0

链接到https://unix.stackexchange.com/questions/3595/ubuntu-list-explicitly-installed-packages/3624#3624的人确实有很好的解决方案,但是它不能作为智能应用的输出正常运行已经改变。这是一个更新的版本,基于与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

您也可以转到另一个站点并在那里更新答案。
Martin Ueding

0

使用分发清单文件作为基本软件包集。将手工安装的结果按体系结构和部分分类到软件包组中,因此将重点放在软件包组上比较容易(也许您不关心某些部分)。

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 <manually_installed.txt

rm info.txt

修改软件包文件很容易,因此每行都带有前缀,apt-get install -y 并且该文件是bash脚本。然后,所有的软件包文件都可以包含在无业游民的供应循环中。
达伦·韦伯

0
#! /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

0

我没有找到适合自己的脚本,所以我写了一个脚本。通过分析/var/log/apt/history.log*和/ var / log / aptitude的内容,然后按日期时间排序,得到两个列表,一个列表是手动安装的pkgs,另一个是已安装但已删除的pkgs。带有“ apt list”验证的脚本。略有偏差,因为使用dpkg安装并修改了PPA源。

我放在这里,https://github.com/eexpress/eexp-bin/blob/master/self-installed-pkg.pl

如果有人需要测试它,也许需要修改一些代码,因为我的日志文件是中英文混合的(特别是RFC2822 datetime格式),我需要处理它。 在此处输入图片说明


那不可读的文字墙截图是什么?
muru

这是我的脚本输出。但是今天我发现Fedora的dnf更有效。“ dnf历史记录”显示软件包操作的纯历史记录。
utopic eexpress

0

我认为您想使用/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,并通过grep传递,并使用apt [-get] install [和/或重新安装]提取行,并显示剩余的行(-o标志),这相当于软件包名称。

sed如果只想在单独的行中使用包名,则需要一些修改(例如,使用)。给读者的练习!

值得注意的是,“状态”部分中的突触软件包管理器(gksu synaptickdesudo synaptic)具有“已安装(手动)”列表。如果将整个列表标记为要删除[不要应用!],则应该能够保存标记的更改并以这种方式获取软件包列表。警告:synaptic对我来说是锁定的(大概是计算依赖项删除)。


我的答案复制到其他地方。
pbhj
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.