Как получить список установленных пакетов без зависимостей?
Центр программного обеспечения как-то показывает довольно короткий список установленных пакетов. Как получить это в текстовом файле?
Я старался:
> dpkg --get-selections|wc -l
3265
> aptitude search '~i!~M'|wc -l
1181
> dpkg -l | grep ^ii | sed 's_ _\t_g' | cut -f 2|wc -l
3076
> dpkg --get-selections | grep -v deinstall|wc -l
3076
> apt-mark showmanual|wc -l
1181
Я знаю, что установил несколько десятков пакетов, а не тысячи. Мне нужны в списке именно те пакеты, которые я бы выбрал без зависимостей, чтобы просмотреть их.
ОБНОВИТЬ
Большое спасибо @kos, я наконец получил список с этой командой:
> zcat /var/log/apt/history.log.*.gz | cat - /var/log/apt/history.log | grep -Po '^Commandline: apt-get install \K.*' | tr ' ' '\n' | grep -v '\-\-reinstall'|grep -v '\-\-force-yes'|grep -v '\-y'|grep -v '\-f'|sort|uniq wc -l
103
6 ответов
Это не дает точного ответа на вопрос: скорее, дает команду перечислить все apt-get install
Команды когда-либо выполнялись вместе с некоторыми советами о том, как анализировать список дальше, чтобы получить список всех apt-get install
Команды когда-либо выполняются, за исключением тех, что выполняются Ubiquity, поскольку идеального решения этой задачи, похоже, не существует.
zcat /var/log/apt/history.log.*.gz | cat - /var/log/apt/history.log | grep -Po '^Commandline:(?= apt-get)(?=.* install ) \K.*'
zcat /var/log/apt/history.log.*.gz
: распаковывает все сжатыеapt
входит в/var/log/apt
соединяет их и печатаетstdout
;cat - /var/log/apt/history.log
: добавляет/var/log/apt/history.log
и печатает наstdout
;grep -Po '^Commandline:(?= apt-get)(?=.* install ) \K.*'
: выбирает только строки, начинающиеся сCommandline: apt-get
содержащийinstall
с начальным и конечным пробелом и печатает остаток от каждой выбранной строки вstdout
;
Это выведет список всех apt-get install
когда-либо выполняются команды (единственным нежелательным выводом может быть apt-get
неопасным install
Команда, упоминающая install
пакет, но этот пакет не существует (пока?), по крайней мере, в репозиториях по умолчанию);
Примечание. В моей установке (Ubuntu 15.04, 64-битная) первые четыре перечисленные команды - это команды, выполняемые Ubiquity во время установки; чтобы исключить их, вы можете передать вывод sed
:
sed '1,4d'
Итак, последняя примерная команда для 64-битной Ubuntu 15.04 будет выглядеть так:
zcat /var/log/apt/history.log.*.gz | cat - /var/log/apt/history.log | grep -Po '^Commandline:(?= apt-get)(?=.* install ) \K.*' | sed '1,4d'
меткий шоу-мануал
предоставит вам список всех установленных вручную пакетов без зависимостей - важно отметить, что он также покажет, какие пакеты были установлены во время установки Ubuntu.
Чтобы записать вывод в файл:
apt-mark showmanual> somefile
На самом деле есть много других способов, таких как использование этой команды
comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort -u)
Хотя я понятия не имею, как работает выше;)
Для просмотра пакетов, установленных по дате:
Пакеты установлены по дате использования cat /var/log/dpkg.log | grep "\ install\ > somefile"
Пакеты, установленные с помощью dpkg
использование ls -l /var/log/dpkg* > somefile
- это, вероятно, то, что вы ищете.
Для просмотра пакетов, установленных с помощью dpkg:
Этот файл содержит вышеуказанную информацию: /var/log/dpkg.log
Вот небольшое улучшение принятого ответа, в котором перечислены команды с датами, в которые они были отправлены, в хронологическом порядке. Я считаю, что хронологический компонент очень полезен, если вы хотите знать, что вы изменили в своей системе.
В исходном ответе также использовались только команды "apt-get install", но недавно apt поддерживал прямые команды "apt install", которые не были захвачены ответом. Я сделал PCRE более мягким, включив в него все подходящие команды.
zcat /var/log/apt/history.log.*.gz | \
cat - /var/log/apt/history.log | \
grep -Po '^Commandline:(?= apt)(?=.* install ) \K.*|^Start-Date: \K.*' | \
grep -B1 "^apt" | \
grep -v -- "^--" | \
paste -d " " - - | \
sort
На самом деле это сложнее, чем кажется, и на Ask Ubuntu есть довольно много похожих вопросов.
Я нашел это, глядя в /var/log/apt/history.log
и старые версии этого журнала в формате gzip, любая вещь, установленная apt-get install
Команда указана как установленная этой командой.
Так:
grep "apt-get install" /var/log/apt/history.log
Покажет вам все за период, который охватывает текущий журнал истории apt. Вам нужно будет gunzip
ваши старые журналы, и grep те, чтобы собрать всю вашу информацию вместе. Все команды grep могут быть перенаправлены в текстовый файл, чтобы получить хороший список.
Это, вероятно, полезно только в том случае, если Software Center использует apt-get install
при установке. Я знаю, что Центр программного обеспечения - это интерфейс для apt
но не уверен, что он использует эту команду явно.
Эта команда выдаст список установленных вручную пакетов, а также тех, у которых были удалены их «автоматически установленные» обратные зависимости (например, если вы удалите метапакет ubuntu-server, его зависимости больше не будут помечаться как автоматические и будут теперь быть в этом списке):
apt list --installed | grep -v automatic
Другими словами, приведенный выше список вернет все пакеты либо без обратных зависимостей, либо где они также помечены как установленные вручную.
Вот скрипт Ruby, который использует rdepends, чтобы проверить, является ли пакет зависимостью для другого установленного пакета. Это не скажет точно, что вы выбрали, но это не зависит от ваших файлов журналов (которые могли быть повернуты).
При установке пакетов, перечисленных в качестве корневых, будут установлены все пакеты, перечисленные в дочерних пакетах. Таким образом, вы должны получить почти (см. Недостатки ниже) тот же список пакетов.
В списке детей будут показаны пакеты, которые являются зависимостями других дочерних пакетов или корневых пакетов.
У этого подхода есть некоторые недостатки:
- Некоторые пакеты могут не отображаться в качестве корневых, если они являются зависимостями какого-либо необязательного, рекомендованного вами выбранного пакета. Например, на моем сервере
apache2
указан в детских пакетах, потому что у меня также естьlibapache2-mod-php
,libapache2-mpm-itk
а такжеpython-letsencrypt-apache
установлены, которые имеютapache2
как зависимость. - Циклические зависимости (пакеты, которые прямо или косвенно зависят друг от друга) будут перечислены в дочерних пакетах (например:
libapache2-mod-php
а такжеlibapache2-mod-php7.0
). Есть раздел, в котором перечислены вероятные циклы (проверьте предки пакетов на 5 поколений), вы должны включить его, чтобы иметь тот же список пакетов (если я не пропустил что-то еще).
#!/usr/bin/env ruby
class ListRootPackages
def run
count = manual_marked_packages.count
@dependencies ||= {}
@root_packages ||= begin
manual_marked_packages.each_with_index.map do |package, index|
STDERR.print " #{index + 1} / #{count} \r"
intersection = manual_marked_packages & reverse_dependencies(package)
if intersection.any?
@dependencies[package] = intersection
nil
else
package
end
end.compact
end
end
def potential_cyclic_dependences
run
@potential_cyclic_dependences ||= @dependencies.keys.map do |package|
package unless has_root_ancestor?(package, 5)
end.compact
end
def has_root_ancestor?(package, level=0)
return true if @root_packages.include?(package)
return false if level.zero?
@dependencies[package].any? { |parent| has_root_ancestor?(parent, level - 1) }
end
def root_packages
run
@root_packages
end
def dependencies
run
@dependencies
end
def manual_marked_packages
@manual_marked_packages ||= parse_cli_list(`apt-mark showmanual`)
end
private
def reverse_dependencies(package)
parse_cli_list(`apt-cache rdepends #{package}`)[2..-1]
end
def parse_cli_list(list)
list.split("\n").map(&:strip)
end
end
list = ListRootPackages.new
list.run
puts "===== Root Packages (#{list.root_packages.count}) ====="
puts list.root_packages.join("\n")
puts
puts "===== Children packages (#{list.dependencies.count}) ====="
puts list.dependencies.map { |package, parents| "#{package}: #{parents.join(', ')}" }.join("\n")
puts
puts "===== Potential cyclic dependencies (#{list.potential_cyclic_dependences.count}) ====="
puts list.potential_cyclic_dependences.join(", ")
если кто-то захочет преобразовать это в Bash или Python, это было бы неплохо, поскольку Ruby реже устанавливается на серверах, чем Bash или Python.