Como replicar a seleção de pacotes instalados de uma instância do Fedora para outra?

16

Eu tenho um sistema Fedora (A) onde instalei alguns pacotes ao longo do tempo. Agora eu quero instalar o Fedora em outro computador (B) e quero instalar os mesmos pacotes nele.

Em termos do Debian, quero realizar algo como isto:

$ dpkg --get-selections > pkg_sel_host_a  # on host_a
$ dpkg --set-selections < pkg_sel_host_a  # on host_b

Mas, para ser sincero, eu realmente quero um método melhor para selecionar os mesmos pacotes no novo sistema Fedora 19 (B): eu só quero instalar os pacotes do sistema A que foram explicitamente mencionados em uma dnf install(ou yum install) linha de comando - e não aqueles que foram instalados como dependências!

Por quê? Porque talvez as dependências tenham mudado - e eu não quero instalar dependências desatualizadas no novo sistema. Além disso, quando removo pacotes, quero remover as (possivelmente) dependências instaladas automaticamente desnecessárias (ou seja, órfãs).

Eu encontrei dnf list installed- mas ele não é exibido se um pacote foi selecionado explicitamente ou apenas foi instalado devido a uma dependência.

Como obtenho essas informações no Fedora?

Qual é a maneira do Fedora / dnf de replicar as seleções de pacotes?

maxschlepzig
fonte

Respostas:

12

Desde o Fedora 26, o repoquery subcomando Dnf suporta uma nova opção para listar todos os pacotes instalados pelo usuário:

$ dnf repoquery --qf '%{name}' --userinstalled \
 | grep -v -- '-debuginfo$' \
 | grep -v '^\(kernel-modules\|kernel\|kernel-core\|kernel-devel\)$' > pkgs_a.lst

Ao contrário de outros métodos, ele também lista todos os pacotes debuginfo. O grep adicional no exemplo acima os filtra.

Para instalar a lista no host B:

$ < pkgs_a.lst xargs dnf -y install

API Dnf

Nas versões recentes do Dnf (por exemplo, Fedora> = 23), o banco de dados do pacote pode ser consultado para nomes de pacotes instalados pelo usuário através da API Dnf Python:

$ python3 -c 'import dnf; b = dnf.Base(); b.fill_sack(); \
  l = sorted(set(x.name for x in b.iter_userinstalled() \
       if not x.name.endswith("-debuginfo") \
          and x.name not in \
             ["kernel-modules", "kernel", "kernel-core", "kernel-devel"] )); \
  print("\n".join(l)) ' > pkgs_a.lst

# dnf install $(cat pkgs_a.lst) # on host_b

Por padrão, dnf installaborta se um ou mais pacotes não estiverem mais disponíveis. Como alternativa, o dnf pode ser forçado a instalar todos os restantes:

# dnf install --setopt=strict=0 $(cat pkgs_a.lst) # on host_b

PS: Coloque o código acima e mais no user-installed.pyque também suporta outras distribuições.

histórico instalado pelo usuário

No Fedora 23 e posterior, o Dnf fornece o

# dnf history userinstalled

comando que lista todos os pacotes instalados pelo usuário. A partir de 2016-11, sua utilidade é limitada, porque não há como controlar sua saída e ela imprime pacotes totalmente qualificados (por exemplo, incluindo informações de versão).

Limitações instaladas pelo usuário

Observe que a marcação de pacotes como instalados pelo usuário tem algumas limitações em algumas versões do Fedora; para os sistemas da era do Fedora 23 (de cerca de 2015-11), os seguintes problemas são relevantes):

Repoquery

Em sistemas Fedora mais antigos, onde o Dnf, a API do Dnf e dnf history userinstallednão está disponível, pode-se usar a recomposição , por exemplo:

$ repoquery --installed \
     --qf '%{n} | %{yumdb_info.reason} | %{yumdb_info.installed_by}' --all \
    | awk -F'|' ' $2 ~ /user/ && ($3 != 4294967295) { print $1 }'  \
    | sort -u > pkgs_a.lst

A segunda condição do awk é usada para excluir pacotes que foram instalados pelo instalador. O ID do usuário do instalador aparentemente foi armazenado como 4294967295 - como alternativa, você pode escrever algo parecido ($3 == 0 || $3 == your-user-id).

Note que este comando funciona no Fedora até a versão 21 - mas, por exemplo, não na versão 23, porque o comando repoqueryfoi substituído por dnf repoquery. E dnf repoquerynão entende a %{yumdb_info.reason}tag.

maxschlepzig
fonte
Não tenho certeza se essa abordagem obterá tudo; notei isso no meu sistema quando executei repoquery ...: "Razão da consulta do yumdb inválida 'motivo' do pkg instalado: HandBrake-cli-0.9.5-1.fc14.x86_64"
slm
@ slm, hm, de qual repositório o freio de mão foi instalado? Talvez a configuração do repositório tenha algo a ver com isso?
maxschlepzig
Eu acho que pode ter sido um RPM independente que eu instalei usando yum localinstall .... Eu tinha uma quantidade razoável de pacotes que caíam naquele campo.
Slm
repoquery --installed --qf '%{n} - %{yumdb_info.reason}' --all 2>&1|grep -v "user$"|grep -v "dep$" |wc -ldevolveu 90 pacotes.
Slm
6

A maneira mais fácil e funcionou por um longo tempo é:

yum-debug-dump => gives file.

yum-debug-restore <file-from-debug-dump>

... que funciona de maneira semelhante ao comando get / set selections dpkg, AIUI. Observe também que se você estiver reproduzindo o histórico, poderá usar:

yum history addon-info last saved_tx => gives file
yum load-tx <file-from-addon-info>

... em vez de ter que analisar você mesmo.

James Antill
fonte
3

Inspirado pela resposta da slm , eu vim com a seguinte solução baseada:yum history

Obtenha todo o histórico detalhado de todas as transações de instalação do yum (ou seja, sem atualizações), excluindo as executadas como parte das ações iniciais do instalador (transações 1 e 2 no meu sistema, atribuídas ao usuário 'Sistema'):

$ yum history list all | awk -F'|' \
                            '$4 ~ /Install/ && $2 !~ /System/ {print $1}' \
    | xargs yum history info > yum_history

Filtre pacotes instalados explicitamente e elimine prefixos de versão.

$ < yum_history grep '[^-]\<Install\>' | \
  awk '{ print $2 }' \
  | sed 's/\(-[0-9]\+:\|-[0-9]\+\.[0-9]\|-[0-9]\+-\|-[0-9]\+git\).\+\(\.fc1[1-7]\.\|\.noarch\).*$//' \
  | sort > hist_pkg_list

A expressão regular feia é necessária para que todos os tipos de sufixos de versão sejam correspondidos.

Os resultados parecem muito bons no meu sistema.

Uma comparação com a recomposição ansatz (no meu sistema):

método # pacotes
―――――――――――――――
repoquery 569
repoquery-2nd 216
yum história 214

(Eu canalizei os resultados da recombinação por meio de classificação -u)

Por que existem diferenças? Porque repoquery inclui todos os pacotes das transações 1 e 2, ou seja, todos os pacotes que foram instalados pelo instalador do Fedora. Isso explica por que o repoquery inclui os pacotes mencionados xorg-x11-drv-mga e friends.

Comparando repoquery-2nd e yum-history mostra que repoquery-2nd é mais preciso - ele não inclui alguns pacotes já removidos. Além disso, inclui alguns (2 no meu sistema) pacotes das operações 'yum update', ao que parece.

Atenção

O método baseado em histórico acima lista apenas todos os pacotes instalados explicitamente durante toda a vida útil do sistema. Ele não equilibra os pacotes que foram removidos em uma transação posterior. Portanto, esse método precisa de uma curadoria manual dos resultados e deve ser usado apenas em sistemas onde repoquerynão estiver disponível.

maxschlepzig
fonte
Ótima maneira de tirar o melhor de nossas respostas! Eu daria a você mais de um +1 se pudesse pela solução eventual + a boa comparação das várias maneiras de fazer isso.
Slm
2

Eu tenho uma versão mais antiga do Fedora (14), então meu yum inclui uma versão menos rica em recursos yum, mas você pode dar uma olhada no yum historyrecurso. Acredito que você pode obter as informações que procura nesse comando.

lista de histórico

$ sudo yum history list
Loaded plugins: langpacks, presto, refresh-packagekit
Adding en_US to language list
ID     | Login user             | Date and time    | Action(s)      | Altered
-------------------------------------------------------------------------------
   862 | System <unset>         | 2013-07-12 18:00 | Install        |    1   
   861 | System <unset>         | 2013-07-09 03:11 | Install        |    1   
   860 | System <unset>         | 2013-07-01 13:40 | Install        |    1   
   859 | System <unset>         | 2013-06-29 22:07 | Install        |    1   
   858 | System <unset>         | 2013-06-25 22:33 | Install        |    1 P<
   857 | System <unset>         | 2013-06-23 22:28 | Update         |    1 >E
   856 | System <unset>         | 2013-06-23 21:33 | Install        |    1   
   ...

Você pode voltar para a primeira transação, passando uma lista de números para yum history list:

$ sudo yum history list `seq 1 10`
Loaded plugins: langpacks, presto, refresh-packagekit
Adding en_US to language list
ID     | Login user             | Date and time    | Action(s)      | Altered
-------------------------------------------------------------------------------
    10 | Sam M. (local) <saml>  | 2010-12-18 23:23 | Install        |    2   
     9 | Sam M. (local) <saml>  | 2010-12-18 23:15 | Install        |   38   
     8 | Sam M. (local) <saml>  | 2010-12-18 23:12 | Install        |    1   
     7 | Sam M. (local) <saml>  | 2010-12-18 23:09 | Install        |    1  <
     6 | Sam M. (local) <saml>  | 2010-12-18 22:37 | Install        |    1 > 
     5 | Sam M. (local) <saml>  | 2010-12-18 21:57 | Install        |    1   
     4 | System <unset>         | 2010-12-18 21:21 | Install        |    5   
     3 | System <unset>         | 2010-12-18 21:18 | Install        |    4   
     2 | System <unset>         | 2010-12-18 21:10 | Install        |    3   
     1 | System <unset>         | 2010-12-18 19:14 | Install        | 1189

informação da história

A seguir, mostramos o que foi instalado como parte da primeira transação yum:

$ sudo yum history info 1 | less
Loaded plugins: langpacks, presto, refresh-packagekit
Adding en_US to language list
Transaction ID : 1
Begin time     : Sat Dec 18 19:14:05 2010
Begin rpmdb    : 0:da39a3ee5e6b4b0d3255bfef95601890afd80709
End time       :            19:42:43 2010 (1718 seconds)
End rpmdb      : 1189:8c21e9e377c3ebdee936916208f74232d5d6235f
User           : System <unset>
Return-Code    : Success
Transaction performed with:
Packages Altered:
    Dep-Install ConsoleKit-0.4.2-3.fc14.x86_64
    Dep-Install ConsoleKit-libs-0.4.2-3.fc14.x86_64
    Dep-Install ConsoleKit-x11-0.4.2-3.fc14.x86_64
    Dep-Install GConf2-2.31.91-1.fc14.x86_64
    Dep-Install GConf2-gtk-2.31.91-1.fc14.x86_64
    Dep-Install ModemManager-0.4-4.git20100720.fc14.x86_64
    Install     NetworkManager-1:0.8.1-10.git20100831.fc14.x86_64
    Dep-Install NetworkManager-glib-1:0.8.1-10.git20100831.fc14.x86_64
    Install     NetworkManager-gnome-1:0.8.1-10.git20100831.fc14.x86_64
    Install     NetworkManager-openconnect-0.8.1-1.fc14.x86_64

Observe como o yum relata se um pacote foi instalado ou instalado explicitamente porque era necessário por uma dependência. Você pode analisar essas informações e obter sua lista de pacotes que foram explicitamente instalados.

slm
fonte
Adicionei uma resposta com base na sua yum historyideia, mas também compara os resultados com o repoquerymétodo baseado. Como efeito colateral, estendi minha resposta de recomposição.
maxschlepzig
1
dnf repoquery --qf "%{name}" --userinstalled > userinstalled.txt
Flo
fonte
1
Ao examinar as outras 5 respostas aqui, o que você vê de diferente na sua resposta? Não há absolutamente nenhuma explicação de por que ou como sua resposta é melhor ou diferente. Seria bom se você pudesse fornecer uma descrição da sua resposta que cubra essas coisas.
Stephen Rauch
@StephenRauch, este comando não está incluído nas outras respostas, porque é uma adição recente ao dnf. A --userinstalledopção foi adicionada ao dnf em maio . Eu testei e fornece resultados precisos. Module os pacotes kernel / kernel-core / kernel-modules que não são realmente instalados pelo usuário. Ele também contém todos os *-debuginfopacotes - mas eles podem ser facilmente filtrados, se necessário.
maxschlepzig
@maxschlepzig, obrigado pelo feedback, mas essa foi realmente uma pergunta retórica, tentando educar / solicitar que o respondente explicasse isso na resposta.
Stephen Rauch
@StephenRauch, bastante justo, algumas edições certamente seriam apropriadas e me permitiriam marcá-lo como resposta aceita.
maxschlepzig
0

Para os pacotes da lista que você tenha instalado, tente este one-liner :

alias yum-userinstall="yumdb search command_line install* | grep command_line\ = | sort | uniq | sed -r -e 's/command_line = (.*)/yum \1/g'"

Resultado:

# yum-userinstall
     yum install bind-utils
     yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
     yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
     yum install lsof
     yum install nano
     yum install nfs-utils libnfsidmap
     yum install nmap-ncat
     yum install openscap-scanner
     yum install open-vm-tools

PS1: não mostra dependências

PS2: é ordenado alfabeticamente

PS3: não mostra se você removeu o pacote posteriormente

Fernando Fabreti
fonte
-1

O que eu fiz (esqueci os detalhes, e eu sou um vagabundo preguiçoso, então ...

Obtenha todos os pacotes instalados: rpm -qa > file

Use sed(1)para se livrar dos números de versão e outros (mantenha a arquitetura, se necessário). Isso exigiu algumas iterações para acertar; você deseja substituir o último trecho -[0-9.]-[0-9].fc23ou similar por nada, mas também existem "números" engraçados da versão.

Após a instalação normal, faça um yum -y install $(< file)(ou dnf, conforme necessário).

Você obterá algumas consequências dos pacotes que não existem mais ou que mudaram de nome ou foram substituídos por outros.

vonbrand
fonte
Ok, mas isso marcará todos os pacotes instalados anteriormente como instalados pelo usuário no host de destino. Mesmo se eles originalmente foram instalados apenas como uma dependência.
21816 maxschlepzig