Como determinar programaticamente a versão mais alta do RPM do kernel instalado?

9

O que eu quero escrever é algo como:

if [ uname -r is not == highest version of kernel RPM installed ]
then
  echo "You need to reboot to use the latest kernel"
fi

O problema é que, se a saída de rpm -q kernelé algo como:

kernel-2.6.32-358.10.2.el6.x86_64
kernel-2.6.32-358.6.1.el6.x86_64

… Como eu determino qual é mais alto? Eu sei que uma classificação simples de string não é confiável (será retrocedida neste exemplo). Existe um atalho com rpm ou eu tenho que analisar tudo e comparar eu mesmo?

sosiouxme
fonte
Você pode usar /var/log/yum.log para isso. Ou 'ls -lht / boot | grep vmlinuz' se o kernel é o que você está interessado.
schaiba
Esses não são métodos confiáveis ​​para determinar qual é uma versão superior. A verificação / inicialização pode incluir kernels destinados a partições com inicialização múltipla totalmente diferentes.
Sosiouxme 21/05
Talvez eu esteja pensando demais. O rpm -q kernel sempre parece listar os kernels em ordem de versão. Isso é confiável?
Sosiouxme 21/05
'ls -lht / boot | grep vmlinuz | grep el6 ':)
schaiba
1
E sort -Vnão dá resultado correto?
Runium

Respostas:

14

TL; DR

A terceira tentativa realmente funciona! Estou deixando as duas primeiras tentativas para que outras pessoas que se deparem com essas perguntas e respostas no futuro esperem ter uma ideia de como é um problema não trivial analisar as informações da versão do RPM e determinar a linhagem que veio primeiro, segundo, etc.

Tentativa 1 (OP disse que não funcionou)

Este comando classificará a saída e fornecerá a você em ordem de versão:

$ rpm -q kernel --queryformat "%{VERSION} %{RELEASE}\n"|sort -n
2.6.18 238.12.1.el5
2.6.18 238.19.1.el5
2.6.18 274.12.1.el5
2.6.18 308.8.2.el5

POR QUE NÃO FUNCIONOU: Uma pessoa ingênua pensaria que você pode usar alguma variante do sortcomando para executar esta tarefa, mas há variabilidade e inconsistência suficientes na formatação das informações reais da versão para um determinado RPM que simplesmente não são '' até a tarefa.

Tentativa 2 (OP disse que não funcionou)

$ rpm -q --last kernel | head -n 1 | cut -d' ' -f1
kernel-2.6.35.14-106.fc14

POR QUE NÃO FUNCIONOU: Eu tinha grandes esperanças de que essa abordagem produzisse os resultados que o OP estava procurando, mas o problema com esse como o @Joel apontou nos comentários, é que a --lastopção está apenas retornando os resultados classificados por a data em que os RPMs foram instalados.

Tentativa nº 3

Este definitivamente fará o trabalho. Encontrei um conjunto de ferramentas chamado RPM Development Tools. Existem duas ferramentas neste conjunto que permitem determinar se uma versão de um RPM é mais recente ou mais antiga que outra.

Se o RPM ainda não estiver instalado, faça o seguinte:

yum install rpmdevtools

A primeira ferramenta útil é chamada rpmdev-vercmp. Essa ferramenta pode comparar dois nomes de RPMs e dizer qual é o mais novo. Por exemplo:

$ rpmdev-vercmp kernel-2.6.35.14-100.fc14.x86_64 kernel-2.6.35.14-103.fc14.x86_64
0:kernel-2.6.35.14-103.fc14.x86_64 is newer

Depois de descobrir isso, estava pronto para montar um script de shell, mas depois percebi, cara, sou preguiçoso, então cutuquei mais alguns minutos e encontrei outra ferramenta na suíte chamada rpmdev-sort.

Esta ferramenta é uma sujeira. Você pode usá-lo da seguinte maneira:

$ rpm -q kernel | rpmdev-sort 
kernel-2.6.35.14-100.fc14.x86_64
kernel-2.6.35.14-103.fc14.x86_64
kernel-2.6.35.14-106.fc14.x86_64

Existem muitas ferramentas nas Ferramentas de Desenvolvimento RPM que podem valer a pena procurar outras pessoas, por isso estou listando-as aqui para referência futura.

$ rpm -q --queryformat '[%{NAME} %{FILEMODES:perms} %{FILENAMES}\n]' rpmdevtools \
    | grep -E "^.* -..x..x..x " \
    | awk '{print $3}'          \
    | sed 's#/usr/bin/##'       \
    | paste - - -               \
    | column -t

annotate-output   checkbashisms    licensecheck
manpage-alert     rpmargs          rpmdev-bumpspec
rpmdev-checksig   rpmdev-cksum     rpmdev-diff
rpmdev-extract    rpmdev-md5       rpmdev-newinit
rpmdev-newspec    rpmdev-packager  rpmdev-rmdevelrpms
rpmdev-setuptree  rpmdev-sha1      rpmdev-sha224
rpmdev-sha256     rpmdev-sha384    rpmdev-sha512
rpmdev-sort       rpmdev-sum       rpmdev-vercmp
rpmdev-wipetree   rpmelfsym        rpmfile
rpminfo           rpmls            rpmpeek
rpmsodiff         rpmsoname        spectool

Uma alternativa ao # 3

Uma alternativa que o OP mencionado nos comentários é usar sort -V. Isso é uma capital -V. Eu nunca tinha ouvido falar dessa mudança também. Na sortpágina do manual:

-V, --version-sort
       natural sort of (version) numbers within text

Acontece que sortele fornece um recurso para classificar os números de versão para que você também possa executar a classificação da seguinte forma:

$ rpm -q kernel | sort -V
kernel-2.6.35.14-100.fc14.x86_64
kernel-2.6.35.14-103.fc14.x86_64
kernel-2.6.35.14-106.fc14.x86_64
slm
fonte
Desculpe, acho que não. Uma simples classificação de string colocaria o kernel-2.6.10 antes do kernel-2.6.9. Isso tem que funcionar genericamente, não apenas para o exemplo.
Sosiouxme 21/05
-n apenas ajuda você com o primeiro número. Tente classificar o seguinte: 2.6.18 238.12.1.el5 2.6.18 238.19.1.el5 2.6.18 274.12.1.el5 2.6.18 274.8.2.el5 A classificação é absolutamente a ferramenta errada aqui, assim como qualquer outra coisa que não sabe nada sobre esquemas de liberação de versão.
Sosiouxme 21/05
O @slm --lastclassifica pelo tempo de instalação do pacote, não será necessariamente o kernel mais recente (se eles fizeram uma instalação manual do rpm de uma versão mais baixa do kernel, por exemplo).
Bratchley
1
classificar -V irá falhar em um contexto. Digamos que você queira comparar duas versões de um pacote - 1.15-abc e 1.15-2ab. O comando de classificação diria que 1,15-abc é maior que 1,15-2ab. Mas, na verdade, por rpm, 2ab é maior que abc.
crisron
1
sort -V muito diferente de rpmdev-sort. Eu não usaria isso com rpms. Tudo bem para uma rápida olhada, mas é isso.
Tommi Kyntola
1

Você realmente precisa usar a biblioteca RPM para obter um bom resultado. O algoritmo de comparação de versões é ... decididamente complexo. Não é trivial reimplementar no shell, mas se você pode usar o Python para fazer a comparação real, isso se torna relativamente simples. Consulte /programming/3206319/how-do-i-compare-rpm-versions-in-python para obter um exemplo de como fazer isso.

John
fonte
1
rpm -q kernel --queryformat="%{buildtime}\t%{name}-%{version}-%{release}.%{arch}\n" | sort -nr | head -1 | cut -f2

Eu acho que a classificação por tempo de construção é menos provável de ter um caso de canto onde falha, ao contrário do tempo de instalação. No entanto, --último é mais arrumado.

Ian
fonte
0

--lastnão informará o número da versão mais alta, mas será solicitado por data de instalação. Então você pode ver a versão mais recente instalada:

[root@xms_apps ~]# rpm -qa kernel-xen --last
kernel-xen-2.6.18-348.1.1.el5                 Tue 29 Jan 2013 02:18:52 PM EST
kernel-xen-2.6.18-308.11.1.el5                Fri 20 Jul 2012 04:00:26 PM EDT
kernel-xen-2.6.18-308.8.2.el5                 Wed 20 Jun 2012 03:32:47 PM EDT

Na maioria das vezes (a menos que eles tenham feito uma instalação manual do kernel), os dois devem ser os mesmos.

Para acertar 100% em 100% do tempo, você terá que baixar as duas versões do kernel para 2.6.*formatar e depois desmembrá-las a partir do 2.6 (o RHEL não irá rebater drasticamente isso em uma única versão, o RHEL5 sempre será um kernel 2.6) e apenas itere sobre cada linha de saída rpm (possivelmente classificada por --lastdesempenho) e compare cada posição com a posição análoga na versão do kernel que você obteve, uname -rse algum número for maior na string do rpm db que a cadeia uname, saia imediatamente com essa mensagem.

Para ajudá-lo, existe uma pergunta semelhante aqui . Mas essa função assume uma notação decimal puramente pontilhada; portanto, você pode comparar a posição numérica antes do hífen (já que existe apenas uma) e usar a função bash dessa pessoa para testar se a versão do patch é maior do unameque na sequência rpm db.

Bratchley
fonte