¿Qué hace esta instrucción 'apt-get remove'?

10

¿Qué hace el siguiente código?

Lo encontré en Internet, así que lo copié y lo pegué en la terminal, pero cuando instalé un nuevo kernel solo detecta el antiguo.

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
fuente
La segunda parte es una expresión regular, que define cómo debe verse el nombre del archivo, pero no exactamente qué nombre de archivo es. ¿Está instalando un núcleo que es su objetivo o está descubriendo exactamente lo que elimina el comando?
Niklas Lindskog
¡Este código no instalará ningún núcleo, pero elimínelos ! No veo qué hace exactamente este comando sed, pero procesa la salida de dpkg -l 'linux-image-*', que enumera todos los paquetes de kernel instalados y filtra algunos de ellos para su eliminación apt-get remove.
Byte Commander
16
Una muy buena regla general para vivir: si no sabes lo que hace un código, no lo pongas en la Terminal hasta que alguien que sepa lo que hace te lo diga. Si está tratando de obtener el núcleo más actualizado, puede consultar askubuntu.com/questions/119080/… en lugar de usar un código que no entiende.
Coronel Trogdor
Los núcleos viejos que se encuentran en el disco no causan problemas, excepto por ocupar espacio en el disco y hacer que el update-grubpaquete (postinst) sea más lento. Si le preocupa no haber arrancado realmente el núcleo al que estaba intentando actualizar, luego ejecute uname -a, o inclusodmesg | less
Peter Cordes
77
"Lo encontré en Internet, así que lo copié y lo pegué en la terminal" NO NO NO NO NO. Terminarás haciendo cosas horribles por accidente. Ejecutar un código que no entiendes da como resultado cosas terribles como destruir tu sistema y patear a los cachorros.
Journeyman Geek

Respuestas:

12

Rompamos el código uno por uno (para mi 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

Entonces esto no haría 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 puede ver , estuvo muy cerca de eliminar mi metapaquete actual del núcleo linux-image-generic 3.13.0.32.38 amd64 Generic Linux kernel image (gracias a esta última sed '/[0-9]/!d'línea), lo cual está mal.

En pocas palabras, esta pieza sedtiene varios problemas. Debe evitarlo para eliminar sus núcleos más antiguos.

EDITAR:

Ya he dicho que el sedcomando tiene problemas. En aras de la extensión, voy a eliminar las dos últimas líneas con el formulario que realmente debería estar funcionando en mi escenario actual.

Las dos últimas líneas en forma modificada:

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

Entonces:

$ 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

¡Eso es muy peligroso!

Ahora muestra lo que esto le haría a mi sistema, con --dry-runel 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 puede ver, eliminará todos mis núcleos actuales, también tenga en cuenta que esto es solo una simulación para que coincida con mi escenario actual y que el original sedpueda mejorarse.

** Tenga en cuenta que el código real funcionará si se realiza una rebootactualización posterior del núcleo como ya mencionó Oli .

EDIT2:

Aquí hay un script simple pero robusto que considerará todas las situaciones y eliminará los núcleos anteriores reales:

#!/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

Si tiene una versión más nueva que la actual, esto le dará una advertencia para reiniciar su computadora primero. También tenga en cuenta que los núcleos más antiguos se conservan debido a una buena razón: si de alguna manera arruina su núcleo actual haciendo que su sistema sea inestable, entonces debería poder iniciar en cualquier núcleo más antiguo.

heemayl
fuente
Um, espera, que? Reemplaza el código de trabajo original con otro código que crees que "realmente debería estar (!!) allí", observa que tu código "fijo" está roto y eliminaría tu núcleo actual, y así concluyes que el código original es " muy peligroso !! " WTF? -1.
Ilmari Karonen
Ciertamente, hay razones válidas para criticar el código original, como se señaló, por ejemplo, en la respuesta de Oli, y estoy seguro de que el código sed podría hacerse más robusto. Pero ese hecho sigue siendo que, en circunstancias normales (por ejemplo, ha reiniciado después de su última actualización del kernel), el código original funciona, mientras que su versión modificada no.
Ilmari Karonen
1
Antes que nada, no debes usar la última palabra que has usado ... ahora, ¿realmente ejecutaste el código real? quitando la apt-getpieza y qué resultado obtuviste?
heemayl
@IlmariKaronen: bueno, estoy segundo contigo en algunos puntos, he modificado la respuesta ..
heemayl
¿Por qué, sí, lo hice ejecutar el comando modificado (la versión que no se desplome debido a la falta de un paréntesis después (([a-z]|-)*, de que es) sin la apt-getpieza antes de criticarlo. En mi sistema, que da salida a las siguientes líneas: 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. ¿Es eso realmente lo que pretendías? (Además, puntos de bonificación si puede averiguar qué núcleos realmente he instalado.)
Ilmari Karonen
12

Este es un esfuerzo para eliminar los núcleos que no son los actuales.

Hay muchos bits de código por ahí que hacen algo como esto y este no es un buen ejemplo . Podría eliminar fácilmente los núcleos más nuevos que los actuales y, por lo tanto, el metapaquete que se instala ( linux-genericet al) si tuviera una actualización y no se reiniciara.

Oli
fuente
2
Y esta no es una buena idea en absoluto. Esos núcleos más antiguos se mantienen por razones, por defecto solo hay 2 antiguos y uno actual.
Barafu Albino