Listar pacotes em um sistema baseado em apt por data de instalação

95

Como posso listar pacotes instalados por data de instalação?

Eu preciso fazer isso no debian / ubuntu. Respostas para outras distribuições também seriam boas.

Eu instalei um monte de coisas para compilar um certo código, e eu quero obter uma lista dos pacotes que eu tive que instalar.

    
por Elazar Leibovich 04.05.2011 / 07:43

9 respostas

62

Distribuições baseadas em RPM, como Red Hat, são fáceis:

rpm -qa --last

No Debian e em outras distribuições baseadas no dpkg, seu problema específico também é fácil:

grep install /var/log/dpkg.log

A menos que o arquivo de registro tenha sido girado, você deve tentar:

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

Em geral, dpkg e apt parecem não acompanhar a data de instalação, devido à falta de tal campo na página dpkg-query man.

E, por fim, os antigos arquivos /var/log/dpkg.log.* serão excluídos pela rotação de log. Dessa forma, não é garantido que você tenha todo o histórico do seu sistema.

Uma sugestão que aparece algumas vezes (por exemplo, este tópico ) é examinar o diretório /var/lib/dpkg/info . Os arquivos sugerem que você pode tentar algo como:

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

Para responder à sua pergunta sobre seleções, aqui está um primeiro passo.

construir lista de pacotes por datas

$ 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

construir lista de pacotes instalados

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

junte-se às 2 listas

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

Por alguma razão, não está imprimindo muitas diferenças para mim, então pode haver um erro ou uma suposição inválida sobre o que --get-selections significa.

Você pode obviamente limitar os pacotes usando find . -mtime -<days> ou head -n <lines> e alterar o formato de saída da maneira que desejar, por exemplo,

$ 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 listar apenas as seleções que foram instaladas (alteradas?) nos últimos 4 dias.

Você provavelmente também pode remover os comandos sort depois de verificar a ordem de classificação usada por dpkg --get-selections e tornar o comando find mais eficiente.

    
por 04.05.2011 / 08:09
19

Mikel mostrou como fazer isso no nível do dpkg . Em particular, /var/lib/dpkg/info/$packagename.list é criado quando o pacote é instalado (e não modificado posteriormente).

Se você usou as ferramentas APT (o que presumivelmente você fez desde que você está preocupado com os pacotes automaticamente instalados manualmente), há um histórico em /var/log/apt/history.log . Contanto que não tenha sido rotacionado, ele rastreia todas as instalações, atualizações e remoções do APT, com uma anotação para pacotes marcados como instalados automaticamente. Este é um recurso bastante recente, introduzido no APT 0.7.26, então no Debian ele apareceu no squeeze. No Ubuntu, o 10.04 possui history.log , mas a anotação instalada automaticamente não está presente até 10.10.

    
por 04.05.2011 / 09:37
5

Áspero, mas 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
    
por 23.04.2013 / 14:06
4

O arquivo /var/log/apt/history.log tem um IMHO de formato inadequado.

Start-Date: {date} {time} Commandline: {command} {options ...} Install: {package (version)}, ..., {package (version)}, ... End-Date: {date} {time}

Eu teria preferido mais um registro formatado em arquivo de log

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

ou algum XML mostrando não apenas um {package} mas qualquer {dependencies}.

Como atualmente implementado, você pode descobrir as informações que procura, mas requer algum processamento forense para extrair os detalhes.

    
por 18.03.2012 / 22:35
2

Isso funciona para mim em um sistema Debian, estou supondo que o formato do arquivo tenha mudado desde 2011. Esse sistema é bem novo, então eu não esperaria para trabalhar em um sistema mais antigo, embora isso possa exigir apenas descompactar os logs e usar um glob para se referir a todos eles.

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

Os dois primeiros campos em cada linha do arquivo /var/log/dpkg.log são a data e a hora. Observe o espaço à direita com a instalação na parte do grep, isso ocorre porque as atualizações podem acionar instalações, mas se eu entendi corretamente, você queria saber o que foi instalado pelos usuários.

    
por 01.07.2015 / 14:44
2

Aqui está o único que todos querem e precisam:

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

O resultado mostrará todos os pacotes (recentemente) instalados e atualizados em ordem cronológica.

A explicação da linha:

  • ls -1t - obtém todos os nomes de arquivos dpkg.log* em ordem cronológica
  • zcat -f - o arquivo IF é do tipo gzip e depois descompacta, ELSE apenas passa o conteúdo.
  • tac - A saída reversa de cat , linha por linha, para garantir que recebamos a ordem cronológica correta.
  • grep - Verifica apenas os pacotes instalados ou upgrade .
  • awk -F ':a' - Separe o campo arquitetura do nome do pacote
  • column -t - bonito imprimir as colunas separadas por espaço

Naturalmente, gostaríamos de criar um alias para isso, mas infelizmente isso não é possível, pois awk depende de aspas simples e duplas. A esse respeito, isso é melhor colocado em um script bash e onde o separador : é tratado melhor para outras arquiteturas na coluna de campo.

A saída é:

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

Drawback:

  • Como mostrado acima, ele só funciona na arquitetura ARM e precisa de pequenas modificações para o separador de campo de arquitetura
  • Precisa ser colocado em um script para um alias fácil
  • Não foi testado em outros sistemas * nix
por 26.04.2018 / 15:43
1

Observando isso porque você mencionou que outras respostas de distribuição são bem-vindas. O rpm tem um grande conjunto de tags de formato de saída, uma das quais é INSTALLTIME. (Usando wget como exemplo)

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

Isso pode ser formatado de algumas maneiras. Eu uso desta maneira:

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

Essas duas páginas têm uma grande quantidade de informações sobre como solucionar problemas de metadados do RPM:

link

link

A classificação dessas informações fornece uma solução funcional para o seu problema.

    
por 03.02.2016 / 16:43
1

GNU / Linux O Debian não possui ferramentas embutidas para este problema, mas todas as informações sobre programas instalados na forma padrão são salvas em arquivos com nome-do-programa.list na localização / var / lib / dpkg / info / . Mas não há informações sobre programas instalados manualmente lá.

Uma solução longa de linha única :

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

Explicação :

  1. ls -rt envia arquivos ordenados por modificação de data na ordem inversa, isto é, com os arquivos mais recentes no final da lista.
  2. stat imprime a data do arquivo em formato legível.
  3. printf exibe o nome do pacote e a data de sua última modificação.
  4. O loop for como um todo imprime nomes de pacotes e datas do mais antigo para o mais novo.

Exemplo de saída (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

O principal defeito desta solução é que ela não é bem testada na produção.

    
por 07.03.2017 / 13:18
0

É difícil, mas funciona tão rapidamente quanto outras soluções. O formato de data é yyyymmddhhmmss, o que significa que um pouco ou reordenação e remoção de formato resultam em um número que pode ser classificado.

Muitos agradecimentos a outras soluções, este pacote de nomes da lista na ordem da instalação que poderia ser usado em um construído para fazer o sistema operacional da cópia.

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}'
    
por 31.07.2018 / 11:39