Что делает эта инструкция 'apt-get remove'?

10

Что делает следующий код?

Я нашел его в интернете, поэтому скопировал и вставил в терминал, но когда я установил новое ядро, оно обнаруживает только старое.

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
источник
Вторая часть - это регулярное выражение, определяющее, как должно выглядеть имя файла, но не точно, какое это имя файла. Это ваша цель - установить ядро ​​или узнать, что именно удаляет команда?
Никлас Линдског
Этот код не установит любое ядро, но удалит их! Я не вижу, что именно делает эта команда sed, но она обрабатывает вывод dpkg -l 'linux-image-*', в котором перечислены все установленные пакеты ядра и отфильтрованы некоторые из них для удаления apt-get remove.
Byte Commander
16
Очень хорошее практическое правило: если вы не знаете, что делает код, не помещайте этот код в терминал, пока кто-то, кто знает, что он делает, не скажет вам. Если вы пытаетесь получить самое свежее ядро, вы можете обратиться к askubuntu.com/questions/119080/… вместо использования кода, который вы не понимаете.
полковник Трогдор
Старые ядра, сидящие на диске, не вызывают проблем, за исключением того, что они занимают место на диске и замедляют работу update-grub(package postinst). Если вы беспокоитесь о том, что на самом деле вы не загрузили ядро, которое пытались обновить, запустите uname -aили даже запуститеdmesg | less
Peter Cordes
7
«Я нашел его в интернете, поэтому скопировал и вставил в терминал» НЕТ НЕТ НЕТ НЕТ НЕТ. Ты будешь делать ужасные вещи случайно. Выполнение кода, которого вы не понимаете, приводит к ужасным вещам, таким как сбивание вашей системы с нуля, и щенки, которых пинают.
Подмастерье Компьютерщик

Ответы:

12

Давайте разберем код один за другим (для моей системы):

$ 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

Так что это ничего не будет делать:

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

Как вы можете видеть, это было очень близко к удалению моего текущего метапакета ядра linux-image-generic 3.13.0.32.38 amd64 Generic Linux kernel image (благодаря этой последней sed '/[0-9]/!d'строке), что неправильно.

Короче говоря, у этой части sedесть несколько проблем. Вы должны избегать этого, чтобы удалить ваши старые ядра.

РЕДАКТИРОВАТЬ:

Я уже говорил, что у sedкоманды есть проблемы. Ради расширения я собираюсь удалить последние две строки с формой, которая на самом деле должна работать в моем текущем сценарии.

Последние две строки в измененном виде:

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

Так:

$ 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

Это очень опасно!

Теперь покажем, что это будет делать с моей системой, --dry-runвыполнив полную apt-get removeкоманду:

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

Как вы видите, это удалит все мои текущие ядра, также обратите внимание, что это всего лишь симуляция, соответствующая моему текущему сценарию, и оригинал sedможно улучшить.

** Обратите внимание, что реальный код будет работать, если выполнить rebootобновление после ядра, как уже упоминал Оли .

EDIT2:

Вот простой, но надежный скрипт, который учитывает все ситуации и удаляет действующие старые ядра:

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

Если у вас есть какая-либо версия, более новая, чем текущая, это предупредит вас о перезагрузке компьютера. Также обратите внимание, что старые ядра сохраняются по уважительной причине: если вы каким-то образом испортите свое текущее ядро, сделав вашу систему нестабильной, вы сможете загрузить любое старое ядро.

heemayl
источник
Подожди, что? Вы заменяете исходный рабочий код другим кодом, который, по вашему мнению, «действительно должен (!!) быть там», замечаете, что ваш «исправленный» код нарушен и удаляет ваше текущее ядро, и таким образом делаете вывод, что исходный код « очень опасно !! " WTF? -1.
Илмари Каронен
Конечно, есть веские причины критиковать исходный код, как указано, например, в ответе Оли, и я уверен, что код sed можно сделать более надежным. Но факт остается фактом: при нормальных обстоятельствах (например, вы перезагружались после последнего обновления ядра) оригинальный код работает, а ваша измененная версия - нет.
Илмари Каронен
1
Прежде всего, вы не должны использовать последнее слово, которое вы использовали .. теперь, вы на самом деле запускали реальный код? удаление apt-getчасти и какой выход вы получили?
Heemayl
@IlmariKaronen: ну, я с тобой второй в некоторых моментах, я изменил ответ ..
Heemayl
Почему, да, я выполнил вашу модифицированную команду (версию, которая не вылетает из-за пропущенной круглой скобки (([a-z]|-)*, то есть) без apt-getчасти перед критикой. В моей системе, он выводит следующие строки: 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. Это действительно то, что вы хотели? (Кроме того, бонусные баллы, если вы можете выяснить, какие ядра я на самом деле установил.)
Ilmari Karonen
12

Это попытка удалить ядра, которые не являются текущими.

Есть много кусков кода, которые делают что-то подобное, и это не очень хороший пример . Он может легко удалить более новые, чем текущие ядра и, следовательно, метапакет, который устанавливается ( linux-genericи др.), Если у вас было обновление и вы не перезагружались.

Оли
источник
2
И это не очень хорошая идея. Те старые ядра хранятся по причине, по умолчанию есть только 2 старых и текущее.
Барафу Альбино