Enumerar paquetes en un sistema basado en apt por fecha de instalación


104

¿Cómo puedo enumerar los paquetes instalados por fecha de instalación?

Necesito hacer esto en debian / ubuntu. Las respuestas para otras distribuciones también serían buenas.

Instalé muchas cosas para compilar un cierto código, y quiero obtener una lista de los paquetes que tuve que instalar.



1
Estaba buscando en Google la "fecha de lanzamiento adecuada" sin suerte, tal vez este comentario ayudará a los futuros googlers.
ThorSummoner

Respuestas:


66

Las distribuciones basadas en RPM como Red Hat son fáciles:

rpm -qa --last

En Debian y otras distribuciones basadas en dpkg, su problema específico también es fácil:

grep install /var/log/dpkg.log

A menos que se haya girado el archivo de registro, en cuyo caso debe intentar:

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

En general, dpkgy aptno parece rastrear la fecha de instalación, debido a la falta de dicho campo en la dpkg-querypágina del manual.

Y, finalmente, los /var/log/dpkg.log.*archivos antiguos se eliminarán mediante la rotación de registros, por lo que no se garantiza que le proporcione el historial completo de su sistema.

Una sugerencia que aparece varias veces (por ejemplo, este hilo ) es mirar el /var/lib/dpkg/infodirectorio. Los archivos allí sugieren que podrías probar algo como:

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

Para responder a su pregunta sobre las selecciones, aquí hay un primer paso.

construir una lista de paquetes por fechas

$ 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

lista de compilación de paquetes instalados

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

únete a las 2 listas

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

Por alguna razón, no está imprimiendo muchas diferencias para mí, por lo que puede haber un error o una suposición no válida sobre lo que --get-selectionssignifica.

Obviamente, puede limitar los paquetes usando find . -mtime -<days>o head -n <lines>, y cambiar el formato de salida como desee, p. Ej.

$ 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

para enumerar solo las selecciones que se instalaron (¿cambiaron?) en los últimos 4 días.

Probablemente también podría eliminar los sortcomandos después de verificar el orden de clasificación utilizado por dpkg --get-selectionsy hacer que el findcomando sea más eficiente.


8
Normalmente me gusta apt-getmás que eso rpm, pero ahora debian obtiene -1 por no guardar la fecha de instalación en la base de datos. El truco de Debian incluye todos los paquetes instalados, no solo los paquetes seleccionados , sino que es un buen comienzo.
Elazar Leibovich

Para Debian, obtienes menos cruft (elimina half-installedentradas) si lo haces:grep install\ /var/log/dpkg.log
Pierz el

@Mikel - Gran respuesta. Extendí el 'recolectar /var/lib/dpkg/info/*.list información de archivo' y agregué código para filtrar todos menos los "paquetes de nivel superior" (paquetes atp de los cuales no dependen otros paquetes atp). Esa < askubuntu.com/a/948532/723997 > post responde a la pregunta "¿Cómo puedo ver el historial de los comandos de instalación de apt-get que he ejecutado manualmente? ".
Craig Hicks

1
Debian / Ubuntu: grep " install " /var/log/dpkg.logenumera solo las líneas de "instalación" en lugar de mostrar también las de "estado".
postre

Si ni apt ni dpkg almacenan la fecha de instalación / modificación, eso me parece bastante inaceptable en 2019. ¿Confiamos en los archivos de registro grepping que pueden estar o no en la máquina? ¿Cómo es este el caso?
theferrit32

20

Mikel ha mostrado cómo hacer esto en el nivel dpkg . En particular, /var/lib/dpkg/info/$packagename.listse crea cuando se instala el paquete (y no se modifica después).

Si usó las herramientas APT (que presumiblemente lo hizo porque le preocupan los paquetes instalados automáticamente o manualmente), hay un historial /var/log/apt/history.log. Mientras no se haya girado, realiza un seguimiento de todas las instalaciones, actualizaciones y eliminaciones de APT, con una anotación para los paquetes marcados como instalados automáticamente. Esta es una característica bastante reciente, introducida en APT 0.7.26, por lo que en Debian apareció en compresión. En Ubuntu, 10.04 tiene history.logpero la anotación instalada automáticamente no está presente hasta 10.10.


1
Como Mikel señaló: "Y, finalmente, los archivos antiguos /var/log/dpkg.log.* se eliminarán mediante la rotación de registros, por lo que no se garantiza que le proporcione el historial completo de su sistema". Consulte esta < askubuntu.com/a/948532/723997 > respuesta para saber cómo detectar los paquetes de nivel superior actuales (es decir, de los que no depende ningún otro paquete)
Craig Hicks

5

Áspero, pero funciona:

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, silbido por analizar la salida de ls. Consulte mywiki.wooledge.org/ParsingLs para obtener notas sobre por qué esto es peligroso / intrínsecamente defectuoso: la opción más segura es usar find -printfo stat --formatgenerar una secuencia que pueda analizarse sin ambigüedades.
Charles Duffy

@CharlesDuffy Buen enlace, pero para simplificar, usar ls -al --time-style=long-isodebería ser útil. Además, probablemente no se haya escuchado que alguien nombre un paquete APT \n\t\r\ven su nombre.
not2qubit

4

El /var/log/apt/history.logarchivo tiene un formato incómodo en mi humilde opinión.

Fecha de inicio: {fecha} {hora} Línea de comando: {comando} {opciones ...} Instalar: {paquete (versión)}, ..., {paquete (versión)}, ... Fecha de finalización: {fecha } {hora}

Hubiera preferido un registro con más formato de archivo de registro

{fecha} {hora} {tab} {paquete} {tab} {versión} {tab} {comando} {opciones} \ n

o algún XML que muestre no solo un {paquete} sino cualquier {dependencias}.

Tal como está implementado actualmente, puede descubrir la información que busca, pero requiere un procesamiento forense para extraer los detalles.


3

Esto funciona para mí en un sistema Debian, supongo que el formato del archivo ha cambiado desde 2011. Este sistema es bastante nuevo, por lo que no esperaría que funcione en un sistema anterior, aunque eso podría requerir descomprimir los registros y usar un globo para referirse a todos ellos.

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

Los primeros dos campos en cada línea del archivo /var/log/dpkg.logson la fecha y la hora. Tenga en cuenta el espacio final con la instalación en la parte grep, esto se debe a que las actualizaciones pueden desencadenar instalaciones, pero si entendí correctamente, querría saber qué instalaron los usuarios.


1
Exactamente lo que hago. Fácil. Pero puede usar zgrep y todos sus registros .gz serán buscados como zgrep 'install' /var/log/dpkg.log*. Coloque el espacio antes de la palabra "instalar" para evitar esas molestas "medias instalaciones". Tuve que usar cut -f1,5 para obtener el campo del nombre del paquete. Por supuesto, eventualmente los viejos registros rotan.
geoO

2

Aquí está la frase que todos quieren y necesitan:

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

El resultado mostrará todos los paquetes (recientemente) instalados y actualizados en orden cronológico.

La explicación de la línea:

  • ls -1t- obtener todos dpkg.log*los nombres de archivos en orden cronológico
  • zcat -f- Si el archivo es del tipo gzip , descomprímalo, ELSE simplemente pasa el contenido.
  • tac- Salida inversa de cat , línea por línea para asegurarse de obtener el orden cronológico correcto.
  • grep- Solo verifique si hay paquetes instalados o actualizados .
  • awk -F ':a'- Separe el campo de arquitectura del nombre del paquete
  • column -t - bonito imprimir las columnas separadas por espacio

Por supuesto, a uno le gustaría hacer un alias para esto, pero desafortunadamente no es posible ya que awk depende de comillas simples y dobles. En ese sentido, esto es mejor ponerlo en un script bash y donde el :separador se maneja mejor para otras arquitecturas en la columna de campo.

El resultado es:

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

Retirarse:

  • Como se muestra arriba, solo funciona en arquitectura ARM y necesita una ligera modificación para el separador de campo de arquitectura
  • Necesita ser puesto en un script para facilitar el alias
  • No se ha probado en otros sistemas * nix

1

Observando esto porque mencionas que otras respuestas de distribución son bienvenidas. rpm tiene un gran conjunto de etiquetas de formato de salida, una de las cuales es INSTALLTIME. (Utilizando wgetcomo ejemplo)

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

Esto se puede formatear de varias maneras. Lo uso de esta manera:

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

Estas dos páginas tienen una tonelada de gran información sobre cómo resolver problemas de metadatos RPM:

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

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

Ordenar esta información le daría una solución funcional para su problema.


1

GNU / Linux Debian no tiene herramientas integradas para este problema, pero toda la información sobre los programas instalados de forma estándar se guarda en archivos con nombre -programa.list en la ubicación / var / lib / dpkg / info / . Pero no hay información sobre programas instalados manualmente allí.


Una solución larga de una sola línea :

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

Explicacion :

  1. ls -rtgenera archivos ordenados por modificación de fecha en orden inverso, es decir , con los archivos más nuevos al final de la lista.
  2. stat imprime la fecha del archivo en forma legible para humanos.
  3. printf muestra el nombre del paquete y la fecha de su última modificación.
  4. El forciclo en su conjunto imprime nombres de paquetes y fechas desde la más antigua hasta la más nueva.

Ejemplo de salida (truncado):

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

El principal defecto de esta solución es que no está bien probada en producción.


Esta es una hermosa solución que hace que el trabajo esté casi terminado. Son solo inconvenientes, es que (1) es muy lento y (2) que solo muestra cuándo se actualizó por última vez un paquete , no ninguna de sus versiones anteriores. Esto, por supuesto, no es un problema de una sola línea, sino de cómo dpkg no realiza un seguimiento de la historia /var/lib/dpkg/info/. Esa es también la razón por la que /var/log/dpkg.log*puede preferirse el uso.
not2qubit

1

Es difícil, pero funciona tan rápido como otras soluciones. El formato de fecha es aaaammddhhmmss, lo que significa que un poco de reordenamiento y eliminación de formato da como resultado un número que se puede ordenar.

Muchas gracias a las otras soluciones, esta lista de nombres de paquetes en orden de instalación que podrían usarse en un sistema operativo creado para hacer copias.

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

Bienvenido @ alexander-cave! Agregue algunas líneas de salida para que las personas puedan ver qué tipo de salida esperar.
not2qubit
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.