Elencare i pacchetti su un sistema basato su apt per data di installazione


104

Come posso elencare i pacchetti installati per data di installazione?

Devo farlo su debian / ubuntu. Anche le risposte per altre distribuzioni sarebbero belle.

Ho installato un sacco di cose per compilare un certo pezzo di codice e voglio ottenere un elenco dei pacchetti che dovevo installare.



1
Stavo cercando su Google "la data di uscita" senza fortuna, forse questo commento aiuterà i futuri googler.
ThorSummoner,

Risposte:


67

Le distribuzioni basate su RPM come Red Hat sono facili:

rpm -qa --last

Su Debian e altre distribuzioni basate su dpkg, anche il tuo problema specifico è facile:

grep install /var/log/dpkg.log

A meno che il file di registro non sia stato ruotato, nel qual caso dovresti provare:

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

In generale, dpkge aptnon sembra tenere traccia della data di installazione, a causa della mancanza di un tale campo nella dpkg-querypagina man.

E alla fine i vecchi /var/log/dpkg.log.*file verranno eliminati con la rotazione del registro, quindi in questo modo non è garantito che ti fornisca l'intera cronologia del tuo sistema.

Un suggerimento che appare alcune volte (ad esempio questo thread ) è quello di guardare la /var/lib/dpkg/infodirectory. I file lì suggeriscono che potresti provare qualcosa del tipo:

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

Per rispondere alla tua domanda sulle selezioni, ecco un primo passaggio.

costruire un elenco di pacchetti per date

$ 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

costruire l'elenco dei pacchetti installati

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

unisciti alle 2 liste

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

Per qualche motivo non sta stampando molte differenze per me, quindi potrebbe esserci un bug o un'ipotesi non valida su cosa --get-selectionssignifichi.

È ovviamente possibile limitare i pacchetti utilizzando find . -mtime -<days>o head -n <lines>, e modificare il formato di output come desiderato, ad es

$ 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

per elencare solo le selezioni installate (modificate?) negli ultimi 4 giorni.

Probabilmente potresti anche rimuovere i sortcomandi dopo aver verificato l'ordinamento utilizzato da dpkg --get-selectionse rendere il findcomando più efficiente.


8
Di solito mi piace di apt-getpiù rpm, ma ora debian ottiene -1 per non aver salvato la data di installazione nel database. Il trucco debian include tutti i pacchetti installati, non solo i pacchetti selezionati , ma è un buon inizio.
Elazar Leibovich,

Per Debian ottieni meno cruft (rimuove le half-installedvoci) se lo fai:grep install\ /var/log/dpkg.log
Pierz,

@Mikel - Ottima risposta. Ho ampliato le "informazioni sul file /var/lib/dpkg/info/*.list" e ho aggiunto il codice per filtrare tutti tranne i "pacchetti di livello superiore" (pacchetti atp dai quali non dipendono altri pacchetti atp). Quel < askubuntu.com/a/948532/723997 > post risponde alla domanda "Come posso visualizzare la cronologia dei comandi di installazione di apt-get che ho eseguito manualmente? ".
Craig Hicks il

1
Debian / Ubuntu: grep " install " /var/log/dpkg.logelenca solo le linee di "installazione" anziché mostrare anche quelle di "stato".
Dessert,

Se né apt né dpkg store installano / modificano datetime, questo mi sembra inaccettabile nel 2019. Facciamo affidamento su file di log grepping che potrebbero essere o meno ancora sulla macchina? Come va?
theferrit32

20

Mikel ha mostrato come farlo a livello di dpkg . In particolare, /var/lib/dpkg/info/$packagename.listviene creato quando il pacchetto è installato (e non modificato in seguito).

Se hai usato gli strumenti APT (cosa che probabilmente hai fatto dato che sei preoccupato per i pacchetti installati automaticamente o manualmente), c'è una cronologia /var/log/apt/history.log. Finché non si è allontanato, tiene traccia di tutte le installazioni, gli aggiornamenti e le rimozioni di APT, con un'annotazione per i pacchetti contrassegnati come installati automaticamente. Questa è una funzionalità abbastanza recente, introdotta in APT 0.7.26, quindi in Debian è apparsa in compressione. In Ubuntu, 10.04 ha, history.logma l'annotazione installata automaticamente non è presente fino al 10.10.


1
Come ha sottolineato Mikel: "E alla fine i vecchi file /var/log/dpkg.log.* verranno eliminati mediante la rotazione dei registri, in questo modo non è garantito che ti fornisca l'intera cronologia del tuo sistema.". Vedi questa < askubuntu.com/a/948532/723997 > risposta per come rilevare gli attuali pacchetti di livello superiore (ovvero quelli da cui dipende nessun altro pacchetto)
Craig Hicks,

5

Ruvido, ma funziona:

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
Boo, sibilo per l'analisi dell'output da ls. Vedi mywiki.wooledge.org/ParsingLs per le note sul perché questo è pericoloso / intrinsecamente difettoso: l'opzione più sicura è utilizzare uno find -printfo stat --formatgenerare un flusso che può essere analizzato in modo inequivocabile.
Charles Duffy,

@CharlesDuffy Bel link, ma ai fini della semplicità, l'utilizzo ls -al --time-style=long-isodovrebbe essere utile. Inoltre, è probabile che qualcuno abbia chiamato un pacchetto APT con il \n\t\r\vsuo nome.
not2qubit,

4

Il /var/log/apt/history.logfile ha un formato IMHO scomodo.

Data di inizio: {data} {ora} Riga di comando: {comando} {opzioni ...} Installa: {pacchetto (versione)}, ..., {pacchetto (versione)}, ... Data di fine: {data } {tempo}

Avrei preferito un record formattato con più file di registro

{Data} {ora} {tab} {package} {tab} {version} {tab} {comando} {opzioni} \ n

o alcuni XML che mostrano non solo un {pacchetto} ma eventuali {dipendenze}.

Come attualmente implementato, puoi scoprire le informazioni che cerchi ma richiede un'elaborazione forense per estrarre i dettagli.


3

Questo funziona per me su un sistema Debian, suppongo che il formato del file sia cambiato dal 2011. Questo sistema è abbastanza recente, quindi non mi aspetto che funzioni su un sistema più vecchio, anche se potrebbe richiedere solo decomprimere i log e usare un glob per riferirsi a tutti loro.

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

I primi due campi in ciascuna riga del file /var/log/dpkg.logsono la data e l'ora. Nota lo spazio finale con installazione nella parte grep, questo perché gli aggiornamenti possono innescare installazioni ma se ho capito bene volevi sapere cosa è stato installato dagli utenti.


1
Esattamente quello che faccio. Facile. Ma puoi usare zgrep e tutti i tuoi registri .gz verranno cercati come zgrep 'install' /var/log/dpkg.log*. Posiziona lo spazio prima della parola "installa" per evitare quelle fastidiose "mezze installazioni". Ho dovuto usare cut -f1,5 per ottenere il campo del nome del pacchetto. Naturalmente alla fine i vecchi registri ruotano fuori.
geoO,

2

Ecco il one-liner che tutti vogliono e di cui hanno bisogno:

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

Il risultato mostrerà tutti i pacchetti (recentemente) installati e aggiornati in ordine cronologico.

La spiegazione della linea:

  • ls -1t- Ottieni tutti dpkg.log*i nomi dei file in ordine cronologico
  • zcat -f- Se il file è di tipo gzip, decomprimilo, ELSE passa semplicemente il contenuto.
  • tac- Uscita inversa di cat , riga per riga per essere sicuri di ottenere l'ordine cronologico corretto.
  • grep- Controlla solo i pacchetti installati o di aggiornamento .
  • awk -F ':a'- Separare il campo dell'architettura dal nome del pacchetto
  • column -t - piuttosto stampa le colonne separate da spazio

Ovviamente si vorrebbe creare un alias per questo, ma sfortunatamente non è possibile poiché awk dipende da virgolette singole e doppie. A tale proposito, è meglio inserirlo in uno script bash e in cui il :separatore viene gestito meglio per altre architetture nella colonna del campo.

L'output è:

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

Inconveniente:

  • Come mostrato sopra, funziona solo su architettura ARM e necessita di lievi modifiche per il separatore di campi di architettura
  • Deve essere inserito in uno script per un semplice alias
  • Non è stato testato su altri sistemi * nix

1

Notando questo perché dici che altre risposte alla distribuzione sono benvenute. rpm ha un ampio set di tag di formato di output, uno dei quali è INSTALLTIME. (Usando wgetcome esempio)

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

Questo può essere formattato in alcuni modi. Lo uso in questo modo:

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

Queste due pagine contengono moltissime informazioni sulla risoluzione dei problemi relativi ai metadati RPM:

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

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

L'ordinamento di queste informazioni ti darebbe una soluzione funzionante per il tuo problema.


1

GNU / Linux Debian non ha strumenti integrati per questo problema, ma tutte le informazioni sui programmi installati in modo standard vengono salvate in file con nome -programma.elenco nella posizione / var / lib / dpkg / info / . Ma non ci sono informazioni sui programmi installati manualmente lì.


Una lunga soluzione a linea singola :

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

Spiegazione :

  1. ls -rtgenera i file ordinati per modifica della data in ordine inverso, ovvero con i file più recenti alla fine dell'elenco.
  2. stat stampa la data del file in forma leggibile.
  3. printf visualizza il nome del pacchetto e la data dell'ultima modifica.
  4. Il forciclo nel suo insieme stampa i nomi e le date dei pacchetti dal più vecchio al più recente.

Esempio di output (troncato):

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

Il principale difetto di questa soluzione è che non è ben testato in produzione.


Questa è una bella soluzione che fa quasi il lavoro. Gli svantaggi sono solo che (1) è molto lento e (2) mostra solo quando un pacchetto è stato aggiornato l'ultima volta , non una delle sue versioni precedenti. Questo, ovviamente, non è un problema del one-liner, ma di come dpkg non tenga traccia della storia /var/lib/dpkg/info/. Questo è anche il motivo per cui /var/log/dpkg.log*è preferibile utilizzare.
not2qubit,

1

È approssimativo, ma funziona rapidamente come altre soluzioni. Il formato della data è yyyymmddhhmmss, il che significa che un po 'o il riordino e la rimozione del formato danno come risultato un numero che può essere ordinato.

Mille grazie alle altre soluzioni, questo elenco elenca i nomi dei pacchetti in ordine di installazione che potrebbero essere utilizzati in un sistema operativo creato per creare copie.

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

Benvenuto @ alexander-cave! Aggiungi alcune righe di output in modo che le persone possano vedere quale tipo di output aspettarsi.
not2qubit,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.