Список пакетов в системе на основе apt по дате установки

104

Как я могу перечислить установленные пакеты по дате установки?

Мне нужно сделать это в Debian / Ubuntu. Ответы для других дистрибутивов также были бы хорошими.

Я установил много вещей для компиляции определенного фрагмента кода и хочу получить список пакетов, которые мне пришлось установить.

Элазар Лейбович
источник
1
Смотрите также Как получить историю установки apt-get .
Микель
1
Я безуспешно гуглял на «подходящую дату выпуска», возможно, этот комментарий поможет будущим гуглерам.
ThorSummoner

Ответы:

67

Дистрибутивы на основе RPM, такие как Red Hat, просты:

rpm -qa --last

В Debian и других дистрибутивах на основе dpkg ваша конкретная проблема также проста:

grep install /var/log/dpkg.log

Если файл журнала не был повернут, в этом случае вы должны попробовать:

grep install /var/log/dpkg.log /var/log/dpkg.log.1

В общем, dpkgи apt, кажется, не отслеживать дату установки, если не считать такого поля на dpkg-queryстранице руководства .

И, в конце концов, старые /var/log/dpkg.log.*файлы будут удалены путем ротации журналов, так что не гарантируется, что вы получите всю историю вашей системы.

Одно предложение, которое появляется несколько раз (например, эта ветка ), - это посмотреть /var/lib/dpkg/infoкаталог. Файлы там предлагают вам попробовать что-то вроде:

ls -t /var/lib/dpkg/info/*.list | sed -e 's/\.list$//' | head -n 50

Чтобы ответить на ваш вопрос о выборе, вот первый проход.

составить список пакетов по датам

$ find /var/lib/dpkg/info -name "*.list" -exec stat -c $'%n\t%y' {} \; | \
    sed -e 's,/var/lib/dpkg/info/,,' -e 's,\.list\t,\t,' | \
    sort > ~/dpkglist.dates

построить список установленных пакетов

$ dpkg --get-selections | sed -ne '/\tinstall$/{s/[[:space:]].*//;p}' | \
    sort > ~/dpkglist.selections

присоединиться к 2 спискам

$ join -1 1 -2 1 -t $'\t' ~/dpkglist.selections ~/dpkglist.dates \
    > ~/dpkglist.selectiondates

По какой-то причине для меня не очень много различий, поэтому может быть ошибка или неверное предположение о том, что --get-selectionsзначит.

Очевидно, что вы можете ограничить пакеты либо с помощью find . -mtime -<days>или head -n <lines>, и изменить формат вывода, как вам нравится, например

$ find /var/lib/dpkg/info -name "*.list" -mtime -4 | \
    sed -e 's,/var/lib/dpkg/info/,,' -e 's,\.list$,,' | \
    sort > ~/dpkglist.recent

$ join -1 1 -2 1 -t $'\t' ~/dpkglist.selections ~/dpkglist.recent \
    > ~/dpkglist.recentselections

перечислить только те варианты, которые были установлены (изменены?) за последние 4 дня.

Вы также можете удалить sortкоманды после проверки используемого порядка сортировки dpkg --get-selectionsи сделать findкоманду более эффективной.

Mikel
источник
8
Я обычно люблю apt-getбольше, чем rpm, но теперь Debian получает -1 за то, что не сохранил дату установки в базе данных. Уловка Debian включает в себя все установленные пакеты, а не только выбранные , но это хорошее начало.
Элазар Лейбович
Для Debian вы получаете меньше хулиганства (удаляет half-installedзаписи), если вы делаете:grep install\ /var/log/dpkg.log
Pierz
@Mikel - Отличный ответ. Я расширил раздел «Информация о сборе /var/lib/dpkg/info/*.list» и добавил код для фильтрации всего, кроме «пакетов верхнего уровня» (пакетов atp, от которых не зависят другие пакеты atp). Этот < askubuntu.com/a/948532/723997 > post отвечает на вопрос «Как я могу просмотреть историю команд apt-get install, которые я выполнил вручную? ».
Крейг Хикс,
1
Debian / Ubuntu: grep " install " /var/log/dpkg.logперечисляет только строки «install», а не показывает «status».
десерт
Если ни apt, ни dpkg store не устанавливают / не изменяют дату и время, это кажется мне совершенно неприемлемым в 2019 году. Мы полагаемся на поиск файлов журналов, которые могут быть на компьютере или нет? Как это так?
theferrit32
20

Микель показал, как это сделать на уровне dpkg . В частности, /var/lib/dpkg/info/$packagename.listсоздается, когда пакет установлен (а не изменен впоследствии).

Если вы использовали инструменты APT (что вы, вероятно, и сделали, так как вас беспокоит автоматическая установка против пакетов, установленных вручную), то есть история /var/log/apt/history.log. Пока он не свернут, он отслеживает все установки, обновления и удаления APT с аннотацией для пакетов, помеченных как автоматически установленные. Это довольно недавняя функция, представленная в APT 0.7.26, поэтому в Debian она появилась в squeeze. В Ubuntu 10.04 имеет, history.logно автоматически установленная аннотация отсутствует до 10.10.

жилль
источник
1
Как заметил Микель: «И в конце концов старые файлы /var/log/dpkg.log.* будут удалены путем ротации журналов, поэтому этот путь не гарантирует полную историю вашей системы». См. Этот < askubuntu.com/a/948532/723997 > ответ о том, как обнаружить текущие пакеты верхнего уровня (то есть те, от которых не зависит ни один другой пакет)
Крейг Хикс,
5

Грубо, но работает:

for fillo in `ls -tr /var/lib/dpkg/info/*.list` ; 
    do basename ${fillo} | sed 's/.list$//g' ; 
done > forens.txt

ls -ltr /var/lib/dpkg/info/*.list > forentime.txt

for lint in `cat forens.txt` ; do 
    echo -n "[ ${lint} Installed ] : " ; 
    echo -n "`grep /${lint}.list forentime.txt | awk '{ print $6, $7, $8 }'` : " ; 
    ( ( grep -A3 " ${lint}$" /var/lib/apt/extended_states | \
        grep '^Auto' > /dev/null ) && echo "Auto" ) || echo "Manual" ; 
done > pkgdatetime.txt
Dulantha
источник
2
Бу, шипение для разбора вывода из ls. См. Mywiki.wooledge.org/ParsingLs для заметок о том, почему это опасно / по своей сути глючит - более безопасный вариант - использовать find -printfили stat --formatгенерировать поток, который может быть однозначно проанализирован.
Чарльз Даффи
@CharlesDuffy Хорошая ссылка, но для простоты, использование ls -al --time-style=long-isoдолжно быть полезным. Кроме того, вероятно, неслыханно, что кто-то назовет пакет APT с \n\t\r\vего именем.
not2qubit
4

/var/log/apt/history.logФайл имеет неудобный формат ИМХО.

Дата начала: {date} {время} Командная строка: {команда} {опции ...} Установка: {пакет (версия)}, ..., {пакет (версия)}, ... Дата окончания: {дата } {время}

Я бы предпочел более отформатированную запись в лог-файле

{Дата} {время} {вкладка} {пакет} {вкладка} {версия} {вкладка} {команда} {опции} \ п

или некоторый XML, показывающий не только {пакет}, но и любые {зависимости}.

В настоящее время реализовано, вы можете найти информацию, которую вы ищете, но для извлечения подробностей требуется некоторая криминалистическая обработка.

Святой ДанБерт
источник
3

Это работает для меня в системе Debian, я предполагаю, что формат файла изменился с 2011 года. Эта система довольно свежа, поэтому я не ожидаю, что это сработает на более старой системе, хотя для этого может потребоваться просто разархивировать журналы и использовать шар, чтобы обратиться ко всем из них.

grep 'install ' /var/log/dpkg.log.1 | sort | cut -f1,2,4 -d' '

Первые два поля в каждой строке файла /var/log/dpkg.log- это дата и время. Обратите внимание на завершающее пространство с установкой в ​​части grep, это потому, что обновления могут инициировать установку, но если я правильно понял, вы хотели знать, что было установлено пользователями.

Амиас
источник
1
Именно то, что я делаю. Легко. Но вы можете использовать zgrep, и все ваши журналы .gz будут искать как zgrep 'install' /var/log/dpkg.log*. Поместите пробел перед словом «установить», чтобы избежать этих надоедливых «половинных установок». Мне пришлось использовать cut -f1,5, чтобы получить поле имени пакета. Конечно, в конце концов старые журналы выворачиваются.
GeoO
2

Вот одна строка, которую каждый хочет и нуждается:

for x in $(ls -1t /var/log/dpkg.log*); do zcat -f $x |tac |grep -e " install " -e " upgrade "; done |awk -F ":a" '{print $1 " :a" $2}' |column -t

Результат покажет все (новые) установленные и обновленные пакеты в хронологическом порядке.

Линия объяснения:

  • ls -1t- получить все dpkg.log*имена файлов в хронологическом порядке
  • zcat -f- Если файл имеет GZIP типа , то разжимать его, ELSE просто передать содержание.
  • tac- Обратный вывод cat , построчно, чтобы убедиться, что мы получаем правильный хронологический порядок.
  • grep- Проверяйте только установленные или обновленные пакеты.
  • awk -F ':a'- Отделите поле архитектуры от имени пакета.
  • column -t - довольно печатать столбцы, разделенные пробелом

Конечно, хотелось бы создать для этого псевдоним, но, к сожалению, это невозможно, поскольку awk зависит как от одинарных, так и от двойных кавычек. В связи с этим это лучше всего поместить в сценарий bash, где :разделитель лучше обрабатывается для других архитектур в столбце поля.

Выход:

2018-03-06  18:09:47  upgrade  libgomp1                     :armhf  6.3.0-18+rpi1                 6.3.0-18+rpi1+deb9u1
2018-03-05  15:56:23  install  mpg123                       :armhf  <none>                        1.23.8-1
2018-03-05  15:56:23  install  libout123-0                  :armhf  <none>                        1.23.8-1
2018-01-22  17:09:45  install  libmailtools-perl            :all    <none>                        2.18-1
2018-01-22  17:09:44  install  libnet-smtp-ssl-perl         :all    <none>                        1.04-1

Минус:

  • Как показано выше, он работает только на архитектуре ARM и нуждается в небольшой модификации для разделителя полей архитектуры
  • Нужно вставить в скрипт для легкого псевдонима
  • Не был протестирован в других системах * nix
not2qubit
источник
1

Отмечая это, вы упоминаете, что приветствуются ответы на другие вопросы. rpm имеет большой набор тегов выходного формата, одним из которых является INSTALLTIME. (Используя wgetв качестве примера)

rpm -qi wget --qf "%{NAME},%{INSTALLTIME}\n" | tail -n 1
wget,1454014156

Это может быть отформатировано несколькими способами. Я использую это таким образом:

rpm -qi wget --qf "%{NAME},%{INSTALLTIME:date}\n" | tail -n 1
wget,Thu 28 Jan 2016 03:49:16 PM EST

На этих двух страницах содержится масса полезной информации по решению проблем метаданных RPM:

http://www.rpm.org/max-rpm/s1-rpm-query-parts.html

http://www.rpm.org/max-rpm/s1-rpm-query-handy-queries.html

Сортировка этой информации даст вам рабочее решение вашей проблемы.

Джонатан Свифт
источник
1

GNU / Linux Debian не имеет встроенных инструментов для этой проблемы, но вся информация о программах, установленных стандартным способом , сохраняется в файлах с именем программы-name.list в каталоге / var / lib / dpkg / info / . Но там нет информации об установленных вручную программах.


Длинное однолинейное решение :

for file_list in `ls -rt /var/lib/dpkg/info/*.list`; do \
    stat_result=$(stat --format=%y "$file_list"); \
    printf "%-50s %s\n" $(basename $file_list .list) "$stat_result"; \
done

Пояснение :

  1. ls -rtвыводит файлы, отсортированные по дате изменения в обратном порядке, то есть с самыми новыми файлами в конце списка.
  2. stat печатает дату файла в удобочитаемой форме
  3. printf отображает название пакета и дату его последнего изменения.
  4. forЦикл в целом имена печатает пакет и даты от старого к новому.

Пример вывода (усеченный):

.........................................
gnome-system-log                            2016-09-17 16:31:58.000000000 +0300
libyelp0                                    2016-09-17 16:32:00.000000000 +0300
gnome-system-monitor                        2016-09-17 16:32:00.000000000 +0300
yelp-xsl                                    2016-09-17 16:32:01.000000000 +0300
yelp                                        2016-09-17 16:32:03.000000000 +0300
gnome-user-guide                            2016-09-17 16:32:18.000000000 +0300
libapache2-mod-dnssd                        2016-09-17 16:32:19.000000000 +0300
.........................................
linux-compiler-gcc-4.8-x86                  2017-02-26 20:11:02.800756429 +0200
linux-headers-3.16.0-4-amd64                2017-02-26 20:11:10.463446327 +0200
linux-headers-3.16.0-4-common               2017-02-26 20:11:17.414555037 +0200
linux-libc-dev:amd64                        2017-02-26 20:11:21.126184016 +0200
openssl                                     2017-02-26 20:11:22.094098618 +0200
unzip                                       2017-02-26 20:11:23.118013331 +0200
wireless-regdb                              2017-02-26 20:11:23.929949143 +0200
nodejs                                      2017-02-26 20:11:33.321424052 +0200
nasm                                        2017-02-28 16:41:17.013509727 +0200
librecode0:amd64                            2017-03-01 10:38:49.817962640 +0200
libuchardet0                                2017-03-01 10:41:10.860098788 +0200
tree                                        2017-03-04 14:32:12.251787763 +0200
libtar0                                     2017-03-07 09:51:46.609746789 +0200
libtar-dev                                  2017-03-07 09:51:47.129753987 +0200

Основным недостатком этого решения является то, что оно недостаточно хорошо протестировано на производстве.

PADYMKO
источник
Это прекрасное решение, которое почти завершило работу. Это только недостатки: (1) он очень медленный и (2) он показывает только когда последний раз обновлялся пакет , а не какая-либо из его предыдущих версий. Это, конечно, не проблема однострочника, но как dpkg не отслеживает историю /var/lib/dpkg/info/. Именно поэтому использование /var/log/dpkg.log*может быть предпочтительным.
not2qubit
1

Это грубо, но работает так же быстро, как и другие решения. Формат даты - ггггммддччммсс, что означает, что бит или переупорядочение и удаление формата приводят к числу, которое можно отсортировать.

Большое спасибо другим решениям, в этом списке перечислены имена пакетов в порядке установки, которые можно было бы использовать во встроенной для копирования операционной системе.

find /var/lib/dpkg/info -name "*.list" -exec stat -c $'%n\t%y' {} \; \
| sed -e 's,/var/lib/dpkg/info/,,' -e 's,\.list\t,\t,' \
| sort | awk '{print $2$3" "$1}' | sed '0,/RE/s/-//' \
| sed '0,/RE/s/-//' | sed '0,/RE/s/://' | sed '0,/RE/s/://' \
| sed '0,/RE/s/\\.//' | sed 's/:armhf//' | sort | awk '{print $2}'
Александровская пещера
источник
Добро пожаловать @ Александр-пещера! Пожалуйста, добавьте несколько строк вывода, чтобы люди могли видеть, какой результат ожидать.
not2qubit