Lister les paquets sur un système basé sur apt par date d'installation


104

Comment puis-je lister les paquets installés par date d'installation?

Je dois le faire sur debian / ubuntu. Des réponses pour d'autres distributions seraient également utiles.

J'ai installé beaucoup de choses pour compiler un certain morceau de code, et je veux obtenir une liste des paquets que j'ai dû installer.



1
J'étais sur Google pour "apt date de sortie" sans succès, peut-être que ce commentaire aidera les futurs googleurs.
ThorSummoner

Réponses:


67

Les distributions basées sur RPM telles que Red Hat sont simples:

rpm -qa --last

Sur Debian et d’autres distributions basées sur dpkg, votre problème spécifique est également simple:

grep install /var/log/dpkg.log

À moins que le fichier journal ait été pivoté, dans ce cas, vous devriez essayer:

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

En général, dpkget aptne semble pas suivre la date d’installation, cela s’appuie sur l’absence d’un tel champ dans la dpkg-querypage de manuel.

Et éventuellement, les anciens /var/log/dpkg.log.*fichiers seront supprimés par la rotation des journaux, de sorte que ce moyen ne vous garantisse pas l’historique complet de votre système.

Une suggestion qui apparaît quelques fois (par exemple ce fil ) est de regarder le /var/lib/dpkg/inforépertoire. Les fichiers suggèrent que vous pourriez essayer quelque chose comme:

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

Pour répondre à votre question sur les sélections, voici un premier passage.

construire la liste des paquets par dates

$ 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

construire la liste des paquets installés

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

rejoindre les 2 listes

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

Pour une raison quelconque, cela n’imprime que très peu de différences pour moi. Il peut donc y avoir un bogue ou une hypothèse invalide concernant la signification --get-selections.

Vous pouvez évidemment limiter les paquets en utilisant find . -mtime -<days>ou head -n <lines>, et changer le format de sortie à votre guise, par exemple

$ 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

pour répertorier uniquement les sélections installées (modifiées?) au cours des 4 derniers jours.

Vous pouvez probablement aussi supprimer les sortcommandes après avoir vérifié l'ordre de tri utilisé dpkg --get-selectionset rendre la findcommande plus efficace.


8
En général, j'aime apt-getplus que rpm, mais maintenant Debian obtient -1 pour ne pas enregistrer la date d'installation dans la base de données. L'astuce Debian inclut tous les paquets installés, pas seulement les paquets sélectionnés , mais c'est un bon début.
Elazar Leibovich,

Pour Debian, vous obtenez moins de crudités (supprime les half-installedentrées) si vous le faites:grep install\ /var/log/dpkg.log
Pierz

@ Mikel - Excellente réponse. J'ai développé les «informations de fichier rassembler /var/lib/dpkg/info/*.list» et ajouté du code pour filtrer tous les packages sauf les «packages de niveau supérieur» (packages atp dont ne dépend aucun autre package atp). Cet < askubuntu.com/a/948532/723997 > post répond à la question "Comment puis-je afficher l'historique des commandes apt-get install que j'ai exécutées manuellement? ".
Craig Hicks

1
Debian / Ubuntu: grep " install " /var/log/dpkg.logrépertorie uniquement les lignes d’installation, plutôt que d’afficher celles de statut.
Dessert

Si ni apt ni dpkg n'ont installé / modifié datetime, cela me semble plutôt inacceptable en 2019. Nous nous sommes basés sur des fichiers de log greping qui peuvent ou non être encore sur la machine? Comment est-ce le cas?
theferrit32

20

Mikel a montré comment faire cela au niveau de dpkg . En particulier, /var/lib/dpkg/info/$packagename.listest créé lors de l’installation du package (et non modifié par la suite).

Si vous avez utilisé les outils APT (ce que vous avez sans doute fait depuis que vous êtes préoccupé par les packages installés automatiquement ou manuellement), il existe un historique dans /var/log/apt/history.log. Tant qu’elle n’est pas retournée, elle garde trace de toutes les installations, mises à niveau et suppressions APT, avec une annotation pour les packages marqués comme installés automatiquement. C'est une fonctionnalité assez récente, introduite dans APT 0.7.26, donc dans Debian, elle est apparue dans squeeze. Dans Ubuntu, 10.04 a, history.logmais l'annotation installée automatiquement n'est pas présente avant 10.10.


1
Comme Mikel l'a fait remarquer: "Et finalement, les anciens fichiers /var/log/dpkg.log.* seront supprimés par la rotation des journaux, de sorte que cette manière de procéder ne donne pas nécessairement l'historique complet de votre système.". Voir cette réponse < askubuntu.com/a/948532/723997 > pour savoir comment détecter les packages de niveau supérieur actuels (c'est-à-dire ceux sur lesquels aucun autre package ne dépend)
Craig Hicks

5

Rugueux, mais fonctionne:

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, sifflement pour l'analyse de la sortie de ls. Voir mywiki.wooledge.org/ParsingLs pour des explications sur les raisons pour lesquelles cela est dangereux / intrinsèquement anormal - l'option la plus sûre consiste à utiliser l'un find -printfou l' autre ou stat --formatà générer un flux pouvant être analysé sans ambiguïté.
Charles Duffy

@ CharlesDuffy Nice lien, mais dans un but de simplicité, l'utilisation ls -al --time-style=long-isodevrait être utile. De plus, il est probablement inouï que quelqu'un nomme un paquet APT \n\t\r\ven son nom.
not2qubit

4

Le /var/log/apt/history.logfichier a un format maladroit IMHO.

Date-début: {date} {heure} Ligne de commande: {commande} {options ...} Installation: {package (version)}, ..., {package (version)}, ... Date-fin: {date } {temps}

J'aurais préféré un enregistrement plus formaté en fichier journal

{date} {heure} {tab} {paquet} {tab} {version} {tab} {commande} {options} \ n

ou un XML montrant non seulement un {package} mais toutes les {dépendances}.

Dans sa version actuelle, vous pouvez découvrir les informations que vous recherchez, mais il faut un traitement judiciaire pour en extraire les détails.


3

Cela fonctionne pour moi sur un système Debian. Je suppose que le format de fichier a changé depuis 2011. Ce système est assez récent, je ne m'attendrais donc pas à ce que cela fonctionne sur un système plus ancien, bien que cela puisse nécessiter simplement de décompresser les journaux et d'utiliser un glob pour se référer à tous.

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

Les deux premiers champs de chaque ligne du fichier /var/log/dpkg.logsont la date et l'heure. Notez la fin de l'espace avec install dans la partie grep, car les mises à niveau peuvent déclencher des installations, mais si j'ai bien compris, vous vouliez savoir ce qui était installé par les utilisateurs.


1
Exactement ce que je fais. Facile. Mais vous pouvez utiliser zgrep et tous vos journaux .gz seront recherchés comme zgrep 'install' /var/log/dpkg.log*. Placez l'espace avant le mot "installer" pour éviter ces ennuyeux "demi-installations". J'ai dû utiliser cut -f1,5 pour obtenir le champ du nom du paquet. Bien sûr, éventuellement, les anciens journaux tournent.
geoO

2

Voici le one-liner que tout le monde veut et a besoin:

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

Le résultat montrera tous les paquets (nouvellement) installés et mis à jour dans un ordre chronologique.

La ligne explication:

  • ls -1t- obtenir tous dpkg.log*les noms de fichiers dans l'ordre chronologique
  • zcat -f- Si le fichier est de type gzip, décompressez-le, ELSE suffit de transmettre le contenu.
  • tac- La sortie inversée du chat , ligne par ligne, permet d’obtenir le bon ordre chronologique.
  • grep- Recherchez uniquement les packages installés ou mis à niveau .
  • awk -F ':a'- Séparer le champ d' architecture du nom du paquet
  • column -t - joli imprimer les colonnes séparées par un espace

On voudrait bien sûr faire un alias pour cela, mais malheureusement ce n’est pas possible car awk dépend de guillemets simples et doubles. À cet égard, il est préférable de l'inscrire dans un script bash et de :mieux gérer le séparateur pour les autres architectures de la colonne de zone.

La sortie est:

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

Inconvénient:

  • Comme indiqué ci-dessus, il ne fonctionne que sur l'architecture ARM et nécessite une légère modification du séparateur de champs d'architecture.
  • Besoin d'être mis dans un script pour facile alias
  • N'a pas été testé sur d'autres systèmes * nix

1

En notant cela parce que vous mentionnez que les autres réponses de distribution sont les bienvenues. rpm a un grand nombre de balises de format de sortie, dont INSTALLTIME. (Utilisation à wgettitre d'exemple)

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

Cela peut être formaté de plusieurs manières. Je l'utilise de cette façon:

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

Ces deux pages contiennent une tonne d'informations utiles sur la résolution des problèmes de métadonnées RPM:

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

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

Le tri de ces informations vous donnerait une solution efficace à votre problème.


1

GNU / Linux Debian n’a pas d’outil intégré à ce problème, mais toutes les informations sur les programmes installés de manière standard sont enregistrées dans des fichiers avec nom -programme.list à l’emplacement / var / lib / dpkg / info / . Mais il n'y a aucune information sur les programmes installés manuellement ici.


Une solution longue ligne unique :

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

Explication :

  1. ls -rtsort les fichiers triés par modification de date dans l'ordre inverse, c'est- à- dire avec les fichiers les plus récents en fin de liste.
  2. stat imprime la date du fichier sous une forme lisible par l'homme.
  3. printf affiche le nom du paquet et la date de sa dernière modification.
  4. La forboucle dans son ensemble imprime les noms de package et les dates du plus ancien au plus récent.

Exemple de sortie (tronqué):

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

Le principal défaut de cette solution est qu’elle n’est pas bien testée en production.


C'est une belle solution qui fait presque le travail. Ce n’est que des inconvénients, c’est que (1) c’est très lent et (2) qu’il n’affiche que la date de la dernière mise à jour d’un paquet , et non l’une de ses versions précédentes. Ceci, bien sûr, n’est pas un problème de one-liner, mais comment dpkg ne garde pas trace de son histoire /var/lib/dpkg/info/. C'est aussi pourquoi utiliser /var/log/dpkg.log*peut être préféré.
not2qubit

1

C'est rude, mais fonctionne aussi rapidement que d'autres solutions. Le format de date est aaaammjjhhmmss, ce qui signifie qu’un peu, une réorganisation ou une suppression de format entraîne un nombre pouvant être trié.

Un grand merci aux autres solutions, cette liste répertorie les noms de paquet dans l’ordre d’installation qui pourraient être utilisés dans un système d’exécution conçu pour la 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}'

Bienvenue @ alexander-cave! Veuillez ajouter quelques lignes de sortie afin que les gens puissent voir à quel type de sortie s'attendre.
not2qubit
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.