O que essa instrução 'apt-get remove' faz?

10

O que o código a seguir faz?

Eu o encontrei na internet, então copiei e colei no terminal, mas quando instalei um novo kernel, ele detectou apenas o antigo.

sudo apt-get remove --purge $(dpkg -l 'linux-image-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d')
medo_alouane
fonte
A segunda parte é uma expressão regular, definindo a aparência do nome do arquivo, mas não exatamente qual o nome do arquivo. Está instalando um kernel que é seu objetivo ou está descobrindo exatamente o que o comando remove?
Niklas Lindskog
Este código não instalará nenhum kernel, mas os remove ! Não vejo exatamente o que esse comando sed faz, mas processa a saída de dpkg -l 'linux-image-*', que lista todos os pacotes de kernel instalados e filtra alguns deles para exclusão por apt-get remove.
Byte Commander
16
Uma regra muito boa de se seguir: se você não sabe o que um código faz, não o coloque no Terminal até que alguém que saiba o que ele faz lhe diga. Se você estiver tentando obter o kernel mais atualizado, consulte o site askubuntu.com/questions/119080/… em vez de usar um código que você não entende.
Coronel Trogdor
Os kernels antigos instalados no disco não causam problemas, exceto ocupando espaço em disco e tornando o update-grub(package postinst) mais lento. Se você está preocupado que você não chegou a inicializar o kernel que você estava tentando atualizar para, em seguida, executar uname -a, ou mesmodmesg | less
Peter Cordes
7
"Encontrei na internet, então copiei e colei no terminal" NÃO NÃO NÃO NÃO NÃO. Você vai acabar fazendo coisas horríveis por acidente. A execução de código que você não entende resulta em coisas terríveis, como ativar o sistema e ativar filhotes.
Journeyman Geek

Respostas:

12

Vamos quebrar o código um por um (para o meu sistema):

$ dpkg -l 'linux-image-*'
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                          Version             Architecture        Description
+++-=============================-===================-===================-================================================================
un  linux-image-3.0               <none>              <none>              (no description available)
ii  linux-image-3.13.0-32-generic 3.13.0-32.57        amd64               Linux kernel image for version 3.13.0 on 64 bit x86 SMP
ii  linux-image-extra-3.13.0-32-g 3.13.0-32.57        amd64               Linux kernel extra modules for version 3.13.0 on 64 bit x86 SMP
ii  linux-image-generic           3.13.0.32.38        amd64               Generic Linux kernel image


$ dpkg -l 'linux-image-*' | sed '/^ii/!d'
ii  linux-image-3.13.0-32-generic                         3.13.0-32.57                                        amd64        Linux kernel image for version 3.13.0 on 64 bit x86 SMP
ii  linux-image-extra-3.13.0-32-generic                   3.13.0-32.57                                        amd64        Linux kernel extra modules for version 3.13.0 on 64 bit x86 SMP
ii  linux-image-generic                                   3.13.0.32.38                                        amd64        Generic Linux kernel image


$ uname -r | sed 's/\(.*\)-\([^0-9]\+\)/\1/'
3.13.0-32



$ dpkg -l 'linux-image-*' | sed '/^ii/!d' | sed "/$(uname -r | sed 's/\(.*\)-\([^0-9]\+\)/\1/')/d"
ii  linux-image-generic                                   3.13.0.32.38                                        amd64        Generic Linux kernel image



$ dpkg -l 'linux-image-*' | sed '/^ii/!d' | sed "/$(uname -r | sed 's/\(.*\)-\([^0-9]\+\)/\1/')/d" | sed 's/^[^ ]* [^ ]* \([^ ]*\).*/\1/'
linux-image-generic



$ dpkg -l 'linux-image-*' | sed '/^ii/!d' | sed "/$(uname -r | sed 's/\(.*\)-\([^0-9]\+\)/\1/')/d" | sed 's/^[^ ]* [^ ]* \([^ ]*\).*/\1/' | sed '/[0-9]/!d'
## No output

Portanto, isso não faria nada:

$ sudo apt-get remove --purge $(dpkg -l 'linux-image-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d')

Como você pode ver , estava muito perto de remover o meu meta pacote atual do kernel linux-image-generic 3.13.0.32.38 amd64 Generic Linux kernel image (graças a esta última sed '/[0-9]/!d'linha), o que está errado.

Em poucas palavras, este pedaço de sedtem vários problemas. Você deve evitá-lo para remover seus kernels mais antigos.

EDITAR:

Eu já disse que o sedcomando tem problemas. Por uma questão de extensão, vou remover as duas últimas linhas com o formulário que realmente deve estar funcionando no meu cenário atual.

As duas últimas linhas em uma forma modificada:

sed -r 's/^[^ ]* *(([a-z]|-)*)(-[a-z]*) *(([0-9]|-)*)\..*/\1-\4\3/'

Assim:

$ dpkg -l 'linux-image-*' | sed '/^ii/!d;/'"$(uname -r | 
sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d' | 
sed -r 's/^[^ ]* *(([a-z]|-)*(-[a-z]*) *(([0-9]|\.|-)*)\..*/\1\-\4\3/'

Outpus:

linux-image-3.13.0.32-generic

Isso é muito vingativo !!

Agora, mostrando o que isso faria com o meu sistema, --dry-running o apt-get removecomando completo :

$ sudo apt-get remove --dry-run $(dpkg -l 'linux-image-*' | 
sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d' | 
sed -r 's/^[^ ]* *(([a-z]|-)*)(-[a-z]*) *(([0-9]|\.|-)*)\..*/\1\-\4\3/')


Reading package lists... Done
Building dependency tree       
Reading state information... Done
Note, selecting 'linux-image-3.13.0-32-generic' for regex 'linux-image-3.13.0.32-generic'
The following package was automatically installed and is no longer required:
  linux-headers-generic
Use 'apt-get autoremove' to remove it.
The following packages will be REMOVED:
  linux-generic linux-image-3.13.0-32-generic
  linux-image-extra-3.13.0-32-generic linux-image-generic
0 upgraded, 0 newly installed, 4 to remove and 0 not upgraded.
Remv linux-generic [3.13.0.32.38]
Remv linux-image-generic [3.13.0.32.38]
Remv linux-image-extra-3.13.0-32-generic [3.13.0-32.57]
Remv linux-image-3.13.0-32-generic [3.13.0-32.57]

Como você vê, ele removerá todos os meus kernels atuais; observe também que isso é apenas uma simulação para corresponder ao meu cenário atual e que o original sedpode ser aprimorado.

** Observe que o código real funcionará se fizer uma rebootatualização posterior ao kernel, como o Oli já mencionou .

EDIT2:

Aqui está um script simples, porém robusto, que considerará todas as situações e removerá os kernels mais antigos reais:

#!/bin/bash
kernels=( $(grep -Po "^linux-image-[^-]+-[^-]+-generic\b" < <(dpkg --get-selections)) )
cur_rel=$(grep -Po ".*(?=-[a-z]*$)" < <(uname -r))

for kernel in "${kernels[@]}"; do
    ker_rel=$(grep -Po "[0-9].*(?=-[a-z]*)" <<< "$kernel")
    dpkg --compare-versions "$ker_rel" gt "$cur_rel" && { echo "Please Restart your computer first"; break; }
    dpkg --compare-versions "$ker_rel" lt "$cur_rel" && sudo apt-get remove "$kernel"
done

Se você possui uma versão mais recente que a atual, isso fornecerá um aviso para reiniciar o computador primeiro. Observe também que os kernels mais antigos são preservados devido a uma boa razão: se você, de alguma forma, atrapalhar o seu kernel atual, tornando o sistema instável, poderá inicializar qualquer kernel mais antigo.

heemail
fonte
Espera, o que? Você substitui o código original em funcionamento por outro código que você acha que "realmente deveria (!!) estar lá", observe que o código "fixo" está quebrado e remove o kernel atual e, portanto, conclui que o código original é " muito vingativo !! "? WTF? -1.
Ilmari Karonen
Certamente existem razões válidas para criticar o código original, como apontado, por exemplo, na resposta de Oli, e tenho certeza de que o código sed poderia ser mais robusto. Mas esse fato permanece que, em circunstâncias normais (por exemplo, você reiniciou após a última atualização do kernel), o código original funciona, enquanto a sua versão modificada não.
Ilmari Karonen
1
Antes de tudo, você não deve usar a última palavra que usou .. agora, você realmente executou o código real? removendo a apt-getpeça e que saída você obteve?
heemayl
@IlmariKaronen: Bem, eu segunda com você em alguns pontos, eu modifiquei a resposta ..
heemayl
Porque, sim, eu queria executar o comando modificado (a versão que não falha devido a um parêntese desaparecidas depois (([a-z]|-)*, que é) sem a apt-getparte antes de criticá-lo. No meu sistema, ele exibe as seguintes linhas: linux-image-3.13-, linux-image-3.13-, linux-image-extra-3.13-, linux-image-extra-3.13-, linux-image-3.13.0.49-generic. É isso mesmo que você pretendia? (Além disso, pontos de bônus se você pode descobrir qual kernels eu realmente ter instalado.)
Ilmari Karonen
12

Este é um esforço para remover os kernels que não são o atual.

Existem muitos bits de código por aí que fazem algo assim e este não é um bom exemplo . Ele poderia remover facilmente os kernels mais recentes que o atual e, portanto, o meta-pacote que instala ( linux-genericet al) se você tivesse uma atualização e não reiniciasse.

Oli
fonte
2
E isso não é uma boa ideia. Esses kernels mais antigos são mantidos por motivos; por padrão, existem apenas 2 antigos e um atual.
Barafu Albino