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

¿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 estarían bien.

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

Comentarios

Respuesta

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 rotado el archivo de registro, en cuyo caso debería intentar:

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

En general, dpkg y apt no parecen rastrear la fecha de instalación, debido a la falta de dicho campo en el dpkg-query página de manual.

Y, finalmente, los archivos /var/log/dpkg.log.* antiguos se eliminarán mediante la rotación de registros, de modo que no » garantizado que le brindará el historial completo de su sistema.

Una sugerencia que aparece varias veces (p. ej. este hilo ) es mirar el directorio /var/lib/dpkg/info. Los archivos allí sugieren que puede intentar 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í «un primer paso.

crear 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 

crear lista 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 » s no imprime muchas diferencias para mí, por lo que podría haber un error o una suposición no válida sobre lo que --get-selections significa.

Obviamente, puede limitar los paquetes ya sea por usando find . -mtime -<days> o head -n <lines>, y cambie el formato de salida como desee, por ejemplo,

$ 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 comandos sort después de verificar el orden de clasificación utilizado por dpkg --get-selections y hacer el find comando más eficiente.

Comentarios

  • Normalmente me gusta apt-get más que 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 ‘ un buen comienzo.
  • Para Debian, obtén menos cruft (elimina half-installed entradas) si lo haces: grep install\ /var/log/dpkg.log
  • @Mikel – Excelente respuesta. Amplié el ‘ recopilar /var/lib/dpkg/info/*.list file info ‘ y agregué código para filtrar todo pero los » paquetes de nivel superior » (paquetes atp de los que no dependen otros paquetes atp). Esa < askubuntu.com/a/948532/723997> publicación responde la pregunta » ¿Cómo puedo ver el historial de los comandos de instalación de apt-get que he ejecutado manualmente? «.
  • Debian / Ubuntu: grep " install " /var/log/dpkg.log enumera solo las líneas de «instalación» en lugar de mostrar las de «estado» también.
  • Si ni apt ni dpkg store instalan / modifican la fecha y hora, eso me parece bastante inaceptable en 2019. ¿Hemos confiado en los archivos de registro grepping que pueden o no estar todavía en la máquina? ¿Cómo es este el caso?

Responder

Mikel ha mostrado cómo hacer esto a nivel dpkg . En particular, /var/lib/dpkg/info/$packagename.list se crea cuando se instala el paquete (y no se modifica posteriormente).

Si usó las herramientas APT (lo que presumiblemente hizo desde que » le preocupan los paquetes instalados automáticamente o manualmente), hay un historial en /var/log/apt/history.log. Siempre que no 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 squeeze. En Ubuntu, 10.04 tiene history.log pero la anotación instalada automáticamente no está presente hasta el 10.10.

Comentarios

  • Como Mikel señaló: » Y, finalmente, los archivos /var/log/dpkg.log.* antiguos se eliminarán mediante la rotación de registros, de modo que de esa manera no es ‘ t garantizado para darle el historial completo de su sistema. «. Ver esto < askubuntu.com/a/948532/723997 > respuesta sobre cómo detectar los paquetes de nivel superior actuales (es decir, aquellos de los que no depende ningún otro paquete)

Respuesta

Difícil, 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 

Comentarios

  • Boo, silbido para analizar la salida de ls. Consulte mywiki.wooledge.org/ParsingLs para obtener notas sobre por qué esto es peligroso / intrínsecamente con errores. La opción más segura es usar find -printf o stat --format para generar una secuencia que se pueda analizar sin ambigüedades.
  • @CharlesDuffy Bonito enlace, pero con el propósito de simplificar, usando ls -al --time-style=long-iso debería ser útil. Además, probablemente no se haya oído que alguien nombre un paquete APT con \n\t\r\v en su nombre.

Respuesta

Aquí está el resumen 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: obtenga todos los dpkg.log* nombres de archivo en orden cronológico
  • zcat -f SI el archivo es de tipo gzip , luego descomprímalo, ELSE simplemente transmita el contenido.
  • tac – Salida inversa de cat , línea por línea para asegurarse de que obtengamos el orden cronológico correcto.
  • grep: solo verifique si está instalado o actualizar paquetes.
  • awk -F ":a" – Separe el campo arquitectura del nombre del paquete
  • column -t – imprime de forma bonita las columnas separadas por espacios

Uno, por supuesto, le gustaría crear un alias para esto, pero desafortunadamente no es posible porque awk depende tanto de single como de doble comillas. En ese sentido, 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 

Inconveniente:

  • Como se muestra arriba, solo funciona en la arquitectura ARM y necesita una ligera modificación para el separador de campo de la arquitectura
  • Debe colocarse en un script para un alias fácil
  • No se ha probado en otros sistemas * nix

Responder

El archivo /var/log/apt/history.log tiene un formato extraño 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

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

o algún XML que muestre no solo un { package} pero cualquier {dependencies}.

Tal como se implementa actualmente, c y descubra la información que busca, pero requiere algún procesamiento forense para extraer los detalles.

Responder

Esto me funciona en un Sistema Debian, supongo que el formato de archivo ha cambiado desde 2011. Este sistema es bastante nuevo, por lo que no esperaría que esto funcione en un sistema más antiguo, aunque eso podría requerir descomprimir los registros y usar un glob para referirse a todos de ellos.

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

Los dos primeros campos en cada línea del archivo /var/log/dpkg.log son 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.

Comentarios

  • 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 » install » para evitar esas molestas » medias instalaciones «. Tuve que usar cut -f1,5 para obtener el campo del nombre del paquete. Por supuesto, eventualmente, los registros antiguos rotan.

Respuesta

GNU / Linux Debian no tiene herramientas integradas para este problema, pero toda la información sobre los programas instalados en la 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 los 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 

Explicación :

  1. ls -rt archivos de salida ordenados por modificación de fecha en orden inverso, es decir con los archivos más recientes al final de la lista.
  2. stat imprime el archivo «s fecha en forma legible por humanos.
  3. printf muestra el nombre del paquete y la fecha de su última modificación.
  4. El for bucle como un todo imprime los nombres de los paquetes y las fechas del más antiguo al más nuevo.

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 bien probado en producto ion.

Comentarios

  • Esta es una hermosa solución que casi hace el trabajo. El único inconveniente ‘ es que (1) es ‘ muy lento y (2) que solo se muestra cuando un paquete se actualizó por última vez , no ninguna ‘ versiones anteriores. Esto, por supuesto, no es un problema de una sola línea, sino cómo dpkg no ‘ realiza un seguimiento del historial en /var/lib/dpkg/info/. Es también por eso que puede ser preferible usar /var/log/dpkg.log*.

Responder

Tomando nota de esto porque menciona 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. (Usando wget como ejemplo)

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

Esto se puede formatear de varias formas. 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 un montón de información excelente 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 brindaría una solución funcional para su problema.

Respuesta

Es tosco, pero funciona tan rápido como otras soluciones. El formato de fecha es aaaammddhhmmss, lo que significa que un poco o un reordenamiento y la eliminación del formato dan 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ía usarse en un sistema operativo construido 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}" 

Comentarios

  • ¡Bienvenido @ alexander-cave! Agregue algunas líneas de resultado para que la gente pueda ver qué tipo de resultado esperar.

Respuesta

Con archivos de registro rotados en apt, podría:

zcat -f /var/log/dpkg.log* | grep " install " | less 

Responder

Lo logré en Kubuntu con los siguientes comandos:

  1. Enumere los paquetes.
  2. lea cada entrada estándar.
  3. almacene el ruta (ruta | fecha de creación) con el formato «% n |% y » en una variable.
  4. almacenar el nombre del archivo en una variable
  5. si ambos comandos anteriores se ejecutaron correctamente, los valores se imprimirán en una sola línea.
ls /var/lib/dpkg/info/*.list |while read xfile; do wpath=$(stat -c "%n|%y" ${xfile}) && wfile=$(basename ${xfile}) && printf "${wfile}|${wpath}\n" ;done 

Saludos cordiales,

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *