Tanto quanto eu posso dizer, não há uma maneira direta de fazer isso. O banco de dados dpkg
contém apenas o estado atual dos pacotes, portanto, qualquer histórico teria que ser deduzido ou analisado dos logs.
Resposta curta (também conhecida como one-liner para o preguiçoso)
dpkg-query -f='${Package}\n' -W | grep -vx "'grep 'Setting up' /var/log/installer/syslog | cut -d' ' -f8'"
Explicação
1. Obtendo uma lista de pacotes instalados pelo instalador
debian-installer
escreve seus registros em /var/log/installer
. Há um arquivo syslog
lá e nós podemos grep
para ver quais pacotes foram instalados:
grep 'Setting up' /var/log/installer/syslog
Note que estamos procurando Configurando ou Desembalando em vez de por exemplo. Selecionando já que queremos todos os pacotes, incluindo aqueles instalados como dependências. Precisamos extrair nomes de pacotes a partir disso:
grep 'Setting up' /var/log/installer/syslog | cut -d' ' -f8
2. Obtendo uma lista de pacotes atualmente instalados
Agora precisamos de uma lista de pacotes atualmente instalados para fazer um reverse grep
contra. Queremos apenas nomes de pacotes, por exemplo. sem descrições para evitar a filtragem muito clara, então dpkg -l
não é ótimo. Podemos usar dpkg-query
em vez disso:
dpkg-query -f='${Package}\n' -W
3. Filtrando pacotes instalados na inicialização
Tudo o que resta fazer é filtrar o conteúdo da primeira lista da segunda lista. Para isso usamos grep -vx
. -v
é para "reverso", -x
(ou --line-regex
) é para "exato". Este último corresponde apenas a linhas inteiras, o que garante que filtramos, por exemplo. apt mas não aptitude .
Então aqui está a coisa toda montada:
# currently installed
current="'dpkg-query -f='${Package}\n' -W'"
# base install (let's also remove duplicates to make verification easier)
base="'grep 'Setting up' /var/log/installer/syslog | cut -d' ' -f8 | sort | uniq'"
# your answer
extra="'echo "$current" | grep -vx "$base"'"
removed="'echo "$base" | grep -vx "$current"'"
4. Verificando resultados
Para verificar se conseguimos os pacotes certos, podemos contar as linhas:
echo "$base" | wc -l # 160
echo "$current" | wc -l # 1677
echo "$extra" | wc -l # 1517
echo "$removed" | wc -l # 0 (I used "netinst")
Atualização: se /var/log/installer
não estiver lá
/var/log/installer
é removido do sistema se o pacote installation-report
for removido. Nesse caso, podemos tentar obter a lista de pacotes que foram carregados pelo instalador do arquivo /var/log/dpkg.log.*
mais antigo.
Existem 2 problemas com isso:
- não há garantia de que as informações de que precisamos ainda estão lá desde que esses arquivos foram girados (ainda no meu caso - instalar em 2010-10-01 e muitas atualizações desde então).
- o arquivo mais antigo provavelmente incluirá logs de pacotes sendo instalados após a instalação inicial.
Não há nada que possamos fazer (1). Com (2) podemos manualmente (por timestamps talvez) estabelecer qual pacote conclui a instalação por debian-installer
. No meu caso, parece ter sido os-prober
(o que acredito ser comum em alguns casos devido a sua relação com grub
).
Veja o código de exemplo para obter $base
usando este método:
last_installed="os-prober"
base_dpkglog="'zgrep ' install ' dpkg.log.8.gz | cut -d' ' -f4 | while read pkg; do
[ "$pkg" != "$last_installed" ] && echo $pkg || { echo $pkg; break; }
done | sort | uniq'"
E uma verificação rápida:
echo "$base_dpkglog" | wc -l # 159
echo "$base" | wc -l # 160
diff -d <(echo "$base") <(echo "$base_dpkglog") # 31d30
# < dpkg