Wyświetla listę pakietów w systemie apt według daty instalacji


104

Jak mogę wyświetlić listę zainstalowanych pakietów według daty instalacji?

Muszę to zrobić na debian / ubuntu. Przydatne byłyby również odpowiedzi dla innych dystrybucji.

Zainstalowałem wiele rzeczy, aby skompilować pewien fragment kodu i chcę uzyskać listę pakietów, które musiałem zainstalować.



1
Googlowałem po „apt release date” bez powodzenia, może ten komentarz pomoże przyszłym pracownikom Google.
ThorSummoner

Odpowiedzi:


66

Dystrybucje oparte na RPM, takie jak Red Hat, są łatwe:

rpm -qa --last

W Debianie i innych dystrybucjach opartych na dpkg twój specyficzny problem jest również łatwy:

grep install /var/log/dpkg.log

Chyba że plik dziennika został obrócony, w takim przypadku powinieneś spróbować:

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

Ogólnie rzecz biorąc, dpkgi aptnie wydaje się, aby śledzić datę instalacji, biorąc pod uwagę brak takiego pola na dpkg-querystronie podręcznika .

I w końcu stare /var/log/dpkg.log.*pliki zostaną usunięte przez rotację logów, więc nie ma gwarancji, że da Ci to całą historię twojego systemu.

Jedną z sugestii, która pojawia się kilka razy (np. Ten wątek ) jest spojrzenie na /var/lib/dpkg/infokatalog. Pliki tam sugerują, że możesz spróbować czegoś takiego:

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

Aby odpowiedzieć na pytanie dotyczące wybranych opcji, oto pierwsze przejście.

buduj listę pakietów według dat

$ 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

buduj listę zainstalowanych pakietów

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

dołącz do 2 list

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

Z jakiegoś powodu nie drukuje dla mnie zbyt wielu różnic, więc może istnieć błąd lub nieprawidłowe założenie dotyczące tego, co --get-selectionsoznacza.

Możesz oczywiście ograniczyć pakiety za pomocą find . -mtime -<days>lub head -n <lines>i zmienić format wyjściowy, jak chcesz, np

$ 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

aby wyświetlić listę tylko tych opcji, które zostały zainstalowane (zmienione?) w ciągu ostatnich 4 dni.

Prawdopodobnie można również usunąć sortpolecenia po sprawdzeniu kolejności sortowania używanej przez dpkg --get-selectionsi zwiększyć findwydajność polecenia.


8
Zwykle apt-getbardziej mi się podoba rpm, ale teraz debian dostaje -1 za nie zapisanie daty instalacji w bazie danych. Sztuczka debiana obejmuje wszystkie zainstalowane pakiety, nie tylko wybrane pakiety, ale to dobry początek.
Elazar Leibovich

W przypadku Debiana otrzymujesz mniej cruft (usuwa half-installedwpisy), jeśli:grep install\ /var/log/dpkg.log
Pierz

@Mikel - Świetna odpowiedź. Rozszerzyłem informacje o pliku „gather /var/lib/dpkg/info/*.list” i dodałem kod, aby odfiltrować wszystkie oprócz „pakietów najwyższego poziomu” (pakiety ATP, od których nie zależą żadne inne pakiety ATP). Ten < askubuntu.com/a/948532/723997 > post odpowiada na pytanie „Jak mogę wyświetlić historię poleceń instalacyjnych apt-get, które ręcznie wykonałem? ”.
Craig Hicks

1
Debian / Ubuntu: grep " install " /var/log/dpkg.logwyświetla tylko linie „instaluj”, a nie pokazuje także „status”.
deser

Jeśli ani apt, ani dpkg store install / zmodyfikowano datetime, wydaje mi się to dość nie do przyjęcia w 2019 roku. Czy polegamy na grepowaniu plików dziennika, które mogą, ale nie muszą znajdować się na komputerze? Jak to się dzieje?
theferrit32

20

Mikel pokazał, jak to zrobić na poziomie dpkg . W szczególności /var/lib/dpkg/info/$packagename.listjest tworzony, gdy pakiet jest instalowany (i nie jest później modyfikowany).

Jeśli korzystałeś z narzędzi APT (co zapewne zrobiłeś, ponieważ martwisz się pakietami instalowanymi automatycznie lub ręcznie), jest historia /var/log/apt/history.log. Tak długo, jak się nie obraca, śledzi wszystkie instalacje, aktualizacje i usuwania APT, z adnotacją dla pakietów oznaczonych jako automatycznie zainstalowane. Jest to dość nowa funkcja, wprowadzona w APT 0.7.26, więc w Debianie pojawiła się w squeeze. W Ubuntu 10.04 ma, history.logale automatycznie zainstalowana adnotacja jest obecna do 10.10.


1
Jak zauważył Mikel: „I w końcu stare pliki /var/log/dpkg.log.* zostaną usunięte przez rotację logów, więc nie ma gwarancji, że da ci to całą historię twojego systemu.”. Zobacz < odpowiedź na pytanie < askubuntu.com/a/948532/723997 >, aby dowiedzieć się, jak wykryć bieżące pakiety najwyższego poziomu (czyli te, od których nie zależy żaden inny pakiet)
Craig Hicks

5

Szorstki, ale działa:

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
Buczenie, syczenie na parsowanie danych wyjściowych ls. Zobacz mywiki.wooledge.org/ParsingLs notatek na dlaczego jest to niebezpieczne / nieodłącznie buggy - bezpieczniejszym rozwiązaniem jest użycie albo find -printflub stat --formatdo generowania strumienia, które mogą być jednoznacznie analizowany.
Charles Duffy

@CharlesDuffy Ładny link, ale dla uproszczenia korzystanie ls -al --time-style=long-isopowinno być pomocne. Ponadto prawdopodobnie nie jest znane, że ktoś nazwałby pakiet APT \n\t\r\vnazwą.
not2qubit

4

/var/log/apt/history.logPlik ma niewygodne formatu IMHO.

Data rozpoczęcia: {data} {czas} Wiersz poleceń: {polecenie} {opcje ...} Zainstaluj: {pakiet (wersja)}, ..., {pakiet (wersja)}, ... Data końcowa: {data } {czas}

Wolałbym bardziej sformatowany plik dziennika

{date} {time} {tab} {package} {tab} {version} {tab} {command} {options} \ n

lub niektóre XML pokazujące nie tylko {pakiet}, ale wszelkie {zależności}.

W chwili obecnej można odkryć poszukiwane informacje, ale wymaga to pewnych analiz kryminalistycznych w celu wyodrębnienia szczegółów.


3

Działa to dla mnie w systemie Debian, zgaduję, że format pliku zmienił się od 2011 roku. Ten system jest dość świeży, więc nie spodziewałbym się, że będzie działać na starszym systemie, chociaż może to wymagać jedynie rozpakowania dzienników i użycia glob odnosi się do nich wszystkich.

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

Pierwsze dwa pola w każdym wierszu pliku /var/log/dpkg.logto data i godzina. Zwróć uwagę na końcowe miejsce z instalacją w części grep, ponieważ aktualizacje mogą wyzwalać instalacje, ale jeśli dobrze zrozumiałem, chciałeś wiedzieć, co zainstalowali użytkownicy.


1
Dokładnie to, co robię. Łatwo. Ale możesz użyć zgrep, a wszystkie twoje logi .gz zostaną przeszukane jak zgrep 'install' /var/log/dpkg.log*. Umieść spację przed słowem „zainstaluj”, aby uniknąć tych nieznośnych „półinstalacji”. Musiałem użyć cut -f1,5, aby uzyskać pole nazwy pakietu. Oczywiście w końcu stare dzienniki się obracają.
Geoo

2

Oto jedna linijka, której wszyscy chcą i potrzebują:

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

Wynik pokaże wszystkie (nowo) zainstalowane i zaktualizowane pakiety w kolejności chronologicznej.

Wyjaśnienie linii:

  • ls -1t- pobierz wszystkie dpkg.log*nazwy plików w kolejności chronologicznej
  • zcat -f- JEŚLI plik jest typu gzip, a następnie rozpakuj go, ELSE po prostu przekaże zawartość.
  • tac- Odwróć wyjście cat , linia po linii, aby upewnić się, że otrzymamy prawidłowy porządek chronologiczny.
  • grep- Sprawdź tylko zainstalowane lub zaktualizowane pakiety.
  • awk -F ':a'- Oddziel pole architektury od nazwy pakietu
  • column -t - całkiem wydrukuj kolumny oddzielone spacją

Oczywiście chcielibyśmy stworzyć dla tego alias, ale niestety nie jest to możliwe, ponieważ awk zależy zarówno od pojedynczych, jak i podwójnych cudzysłowów. W związku z tym najlepiej umieścić to w skrypcie bash i tam, gdzie :separator jest obsługiwany lepiej dla innych architektur w kolumnie pola.

Dane wyjściowe to:

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

Wada:

  • Jak pokazano powyżej, działa tylko na architekturze ARM i wymaga niewielkiej modyfikacji separatora pól architektury
  • Należy umieścić w skrypcie dla łatwego aliasu
  • Nie był testowany w innych systemach * nix

1

Zwracając na to uwagę, ponieważ wspominasz, że inne odpowiedzi dotyczące dystrybucji są mile widziane. rpm ma duży zestaw znaczników formatu wyjściowego, z których jednym jest INSTALLTIME. ( wgetJako przykład)

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

Można to sformatować na kilka sposobów. Używam tego w ten sposób:

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

Te dwie strony zawierają mnóstwo świetnych informacji na temat rozwiązywania problemów z metadanymi RPM:

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

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

Posortowanie tych informacji zapewni działające rozwiązanie problemu.


1

Debian GNU / Linux nie ma wbudowanych narzędzi do tego problemu, ale wszystkie informacje o programach zainstalowanych w standardowy sposób są zapisywane w plikach o nazwie program.list w lokalizacji / var / lib / dpkg / info / . Ale nie ma tam informacji o ręcznie instalowanych programach.


Długie rozwiązanie jednoliniowe :

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

Objaśnienie :

  1. ls -rtwyświetla pliki posortowane według modyfikacji daty w odwrotnej kolejności, tj. z najnowszymi plikami na końcu listy.
  2. stat drukuje datę pliku w postaci czytelnej dla człowieka.
  3. printf wyświetla nazwę pakietu i datę jego ostatniej modyfikacji.
  4. forPętla jako całość nazw pakietów drukuje i terminach od najstarszego do najnowszego.

Przykład wyjścia (obcięty):

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

Główną wadą tego rozwiązania jest to, że nie jest dobrze przetestowany w produkcji.


To piękne rozwiązanie, dzięki któremu praca jest prawie gotowa. To tylko wady, ponieważ (1) jest bardzo wolny i (2) pokazuje tylko, kiedy pakiet był ostatnio aktualizowany , a nie żadna z jego poprzednich wersji. To oczywiście nie jest problem jednej linijki, ale w jaki sposób dpkg nie śledzi historii /var/lib/dpkg/info/. Dlatego też /var/log/dpkg.log*preferowane może być używanie .
not2qubit

1

Jest szorstki, ale działa tak szybko, jak inne rozwiązania. Format daty to rrrrmmddggmmss, co oznacza, że ​​bit lub zmiana kolejności i usunięcie formatu skutkuje liczbą, którą można posortować.

Wiele dzięki innym rozwiązaniom, ta lista nazw pakietów w kolejności instalacji, które mogą być użyte w wbudowanym systemie do kopiowania.

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

Witamy w jaskini Aleksandra! Dodaj kilka wierszy wyników , aby ludzie mogli zobaczyć, jakiego rodzaju wyników się spodziewać.
not2qubit
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.