Was macht diese Anweisung 'apt-get remove'?

10

Was macht der folgende Code?

Ich habe es im Internet gefunden, also habe ich es kopiert und in das Terminal eingefügt, aber wenn ich einen neuen Kernel installiert habe, erkennt er nur den alten.

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
quelle
Der zweite Teil ist ein regulärer Ausdruck, der definiert, wie der Dateiname aussehen soll, aber nicht genau, welcher Dateiname er ist. Installiert es einen Kernel, der Ihr Ziel ist, oder findet es genau heraus, was der Befehl entfernt?
Niklas Lindskog
Dieser Code installiert keinen Kernel, sondern entfernt sie! Ich sehe nicht genau, was dieser sed-Befehl bewirkt, aber er verarbeitet die Ausgabe von dpkg -l 'linux-image-*', die alle installierten Kernel-Pakete auflistet und einige davon zum Löschen herausfiltert apt-get remove.
Byte Commander
16
Eine sehr gute Faustregel: Wenn Sie nicht wissen, was ein Code tut, geben Sie diesen Code erst in Terminal ein, wenn jemand, der weiß, was er tut, es Ihnen sagt. Wenn Sie versuchen, den aktuellsten Kernel zu erhalten, sollten Sie sich askubuntu.com/questions/119080/… ansehen, anstatt einen Code zu verwenden, den Sie nicht verstehen.
Oberst Trogdor
Alte Kernel, die auf der Festplatte update-grubherumliegen, verursachen keine Probleme, außer dass sie Speicherplatz beanspruchen und (Paket nach der Installation) langsamer machen. Wenn Sie befürchten, dass Sie den Kernel, auf den Sie ein Upgrade durchführen wollten, nicht gestartet haben, führen Sie ihn aus uname -aoder sogardmesg | less
Peter Cordes
7
"Ich habe es im Internet gefunden, also habe ich es kopiert und in das Terminal eingefügt" NEIN NEIN NEIN NEIN NEIN. Sie werden am Ende aus Versehen schreckliche Dinge tun. Das Ausführen von Code, den Sie nicht verstehen, führt zu schrecklichen Dingen wie der Zerstörung Ihres Systems und dem Treten von Welpen.
Geselle Geek

Antworten:

12

Lassen Sie uns den Code einzeln brechen (für mein System):

$ 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

Das würde also nichts bewirken:

$ 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')

Wie Sie sehen , war es sehr nahe daran, mein aktuelles Kernel-Metapaket zu entfernen linux-image-generic 3.13.0.32.38 amd64 Generic Linux kernel image (dank dieser letzten sed '/[0-9]/!d'Zeile), was falsch ist.

Kurz gesagt, dieses Stück sedhat mehrere Probleme. Sie sollten es vermeiden, um Ihre älteren Kernel zu entfernen.

BEARBEITEN:

Ich habe bereits gesagt, dass der sedBefehl Probleme hat. Aus Gründen der Erweiterung werde ich die letzten beiden Zeilen mit dem Formular entfernen, das in meinem aktuellen Szenario tatsächlich funktionieren sollte.

Die letzten beiden Zeilen in modifizierter Form:

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

So:

$ 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

Das ist sehr unangenehm !!

Zeigen Sie nun, was dies für mein System bedeuten würde, und geben Sie --dry-runden vollständigen apt-get removeBefehl ein:

$ 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]

Wie Sie sehen, werden alle meine aktuellen Kernel entfernt. Beachten Sie auch, dass dies nur eine Simulation ist, die meinem aktuellen Szenario entspricht und das Original sedverbessert werden kann.

** Beachten Sie, dass der eigentliche Code funktioniert, wenn Sie ein rebootUpgrade nach dem Kernel durchführen, wie Oli bereits erwähnt hat .

EDIT2:

Hier ist ein einfaches, aber robustes Skript, das alle Situationen berücksichtigt und die tatsächlich älteren Kernel entfernt:

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

Wenn Sie eine neuere Version als die aktuelle haben, erhalten Sie eine Warnung, dass Sie Ihren Computer zuerst neu starten müssen. Beachten Sie auch, dass die älteren Kernel aus einem guten Grund erhalten bleiben. Wenn Sie Ihren aktuellen Kernel irgendwie durcheinander bringen und Ihr System instabil machen, sollten Sie in der Lage sein, in jeden älteren Kernel zu booten.

heemayl
quelle
Ähm, warte, was? Sie ersetzen den ursprünglichen, funktionierenden Code durch einen anderen Code, von dem Sie denken, dass er "tatsächlich (!!) vorhanden sein sollte", stellen fest, dass Ihr "fester" Code fehlerhaft ist und Ihren aktuellen Kernel entfernen würde, und schließen daraus, dass der ursprüngliche Code "ist". sehr düster !! "? WTF? -1.
Ilmari Karonen
Es gibt sicherlich triftige Gründe, den ursprünglichen Code zu kritisieren, wie z. B. in Olis Antwort ausgeführt, und ich bin sicher, dass der sed-Code robuster gemacht werden könnte. Es bleibt jedoch die Tatsache, dass unter normalen Umständen (z. B. wenn Sie nach Ihrem letzten Kernel-Upgrade neu gestartet haben) der ursprüngliche Code funktioniert, während Ihre geänderte Version dies nicht tut.
Ilmari Karonen
1
Zunächst sollten Sie nicht das letzte Wort verwenden, das Sie verwendet haben. Haben Sie nun tatsächlich den eigentlichen Code ausgeführt? Entfernen des apt-getTeils und welche Ausgabe haben Sie erhalten?
Heemayl
@IlmariKaronen: Nun, ich bin mit Ihnen in einigen Punkten Zweiter, ich habe die Antwort geändert ..
heemayl
Warum, ja, ich habe Ihren geänderten Befehl (die Version, die aufgrund einer fehlenden Klammer danach nicht abstürzt (([a-z]|-)*) ohne das apt-getTeil ausgeführt, bevor ich es kritisiert habe. Auf meinem System, gibt er die folgenden Zeilen: 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. Ist das wirklich das, was du beabsichtigt hast? (Außerdem Bonuspunkte, wenn Sie herausfinden können, welche Kernel ich tatsächlich installiert habe.)
Ilmari Karonen
12

Dies ist ein Versuch, Kernel zu entfernen, die nicht der aktuelle sind.

Es gibt viele Code-Teile, die so etwas tun, und dies ist kein gutes Beispiel . Es könnte leicht neuere als aktuelle Kernel und damit das Metapaket entfernen, das ( linux-genericua) installiert wird, wenn Sie ein Upgrade hatten und nicht neu starten.

Oli
quelle
2
Und das ist überhaupt keine gute Idee. Diese älteren Kernel werden aus gutem Grund beibehalten. Standardmäßig gibt es nur zwei alte und einen aktuellen.
Barafu Albino