Перерахуйте пакети в підходящій системі за датою встановлення


104

Як я можу перерахувати встановлені пакети за датою встановлення?

Мені потрібно це зробити на debian / ubuntu. Відповіді і для інших розповсюджень були б непогані.

Я встановив багато матеріалів для складання певного коду, і хочу отримати список пакетів, які мені довелося встановити.



1
Я гуглив за "влучною датою випуску" не пощастило, можливо, цей коментар допоможе майбутнім гуглерам.
ThorSummoner

Відповіді:


66

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сторінці man.

І згодом старі /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команду більш ефективною.


8
Мені зазвичай подобається apt-getбільше rpm, але тепер debian отримує -1 за не збереження дати встановлення в базі даних. Трюк Debian включає всі встановлені пакети, не тільки вибрані пакети, але це вдалий початок.
Елазар Лейбович

Для Debian ви отримуєте менше чіткості (видаляє half-installedзаписи), якщо ви робите:grep install\ /var/log/dpkg.log
Pierz

@Mikel - чудова відповідь. Я розширив інформацію про файл файлу "збирати /var/lib/dpkg/info/*.list" і додав код, щоб відфільтрувати всі, крім "пакунків верхнього рівня" (атпакетних пакетів, від яких не залежать інші пакети atp). Це повідомлення < askubuntu.com/a/948532/723997> відповідає на питання "Як я можу переглянути історію команд установки apt-get, які я вручну виконував? ".
Крейг Хікс

1
Debian / Ubuntu: grep " install " /var/log/dpkg.logперераховує лише рядки "встановити", а не показувати "статусні".
десерт

Якщо ані apt, ані dpkg зберігати час встановлення / модифіковану дату, це здається мені неприйнятним у 2019 році. Ми покладаємось на файли журналів, які можуть бути або не знаходяться на машині? Як це так?
theferrit32

20

Мікель показала, як це зробити на рівні dpkg . Зокрема, /var/lib/dpkg/info/$packagename.listстворюється, коли пакет встановлюється (а не змінюється після цього).

Якщо ви використовували інструменти APT (які, імовірно, робили з тих пір, як вас турбує автоматичне відносно встановлених вручну пакетів), існує історія /var/log/apt/history.log. Поки він не обертається, він відслідковує всі установки, оновлення та видалення APT з анотацією до пакетів, позначених як автоматично встановлені. Це досить недавня функція, введена в APT 0.7.26, тому в Debian вона з'явилася в стислі. В 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

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} {time} {tab} {package} {tab} {version} {tab} {command} {options} \ n

або якийсь 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- Зворотний вихід кота , по черзі, щоб гарантувати правильний хронологічний порядок.
  • 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

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

Основний дефект цього рішення - це те, що він недостатньо перевірений у виробництві.


Це прекрасне рішення, завдяки якому робота майже виконана. Є лише недоліками, є те, що (1) це дуже повільно і (2), що він відображається лише тоді, коли пакет був оновлений останнім часом , а не будь-яка його попередня версія. Звичайно, це не проблема однолінійки, але те, як dpkg не відстежує історію /var/lib/dpkg/info/. Ось чому також /var/log/dpkg.log*може бути кращим використання.
not2qubit

1

Це грубо, але працює так само швидко, як і інші рішення. Формат дати - yyyymmddhhmmss, це означає, що біт або переупорядкування та видалення формату призводить до числа, яке можна сортувати.

Завдяки іншим рішенням, цей список перелічує назви в порядку встановлення, яке можна використовувати в побудованій для виготовлення копіювальної операційної системи.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.