Збільшити один вкладиш, щоб видалити лише старі ядра


23

Я бачив багато тем про те, як звільнити місце на / boot розділі, і це також моя мета. Однак мене цікавить лише видалення старих ядер, і не кожного з них, а поточного.

Мені потрібно, щоб рішення було однолінійним, оскільки я буду запускати сценарій з Лялькового, і я не хочу мати зайвих файлів. Поки що я отримав наступне:

dpkg -l linux-* | awk '/^ii/{print $2}' | egrep [0-9] | sort -t- -k3,4 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"` | xargs sudo apt-get -y purge

Якщо бути точнішим, що це робить на даний момент, це наступне:

  • Перерахуйте всі пакети linux- * та надрукуйте їх назви.
  • Перерахуйте лише ті, у яких є числа, і відсортуйте їх, повертаючи зворотний результат. Таким чином, старі ядра перераховані останніми.
  • Друкуйте лише результати, які йдуть за поточним ядром
  • Оскільки є деякі результати linux- {image, headers}, переконайтеся, що я не очищую нічого, що стосується мого поточного ядра
  • Викликати схильність до очищення

Це працює, але я впевнений, що рішення може бути більш елегантним та безпечним для виробничого середовища, оскільки Ubuntu принаймні 20 наших серверів працюють.

Дякую за ваш час, Алехандро.


Щось старе з Мережі: tuxtweaks.com/2010/10/…
користувач68186

Як ви користуєтесь своїм одноклассником, якщо він не збережений у файлі сценарію?
jarno

Відповіді:


25

Виглядає досить приємно, лише кілька коментарів. Два перші коментарі роблять команду більш безпечною, тоді як третій та четвертий роблять її трохи коротшою. Не соромтеся слідкувати за будь-яким із них або ігнорувати їх Хоча я настійно раджу дотримуватися перших двох. Ви хочете переконатися, що це максимально безпечно. Я маю на увазі серйозно. Ви кидаєте sudo apt-get -y purgeдеякий автоматично створений список пакетів. Це так зло ! :)

  1. Перерахувавши все, linux-*ви отримаєте багато помилкових позитивних результатів, таких як (наприклад, з мого результату) linux-sound-base. Незважаючи на те, що вони можуть бути відфільтровані пізніше рештою вашої команди, я особисто почуваю себе безпечнішим, не перелічуючи їх в першу чергу. Краще контролюйте, які пакунки потрібно видалити. Не робіть речей, які можуть мати неочікувані результати. Так я б почав з

    dpkg -l linux-{image,headers}-*
  2. Ваш регекс для "переліку лише тих, у яких є цифри", на мою думку, занадто простий. Наприклад, є пакет, linux-libc-dev:amd64коли ви перебуваєте в 64-бітній системі. Ваш регекс буде відповідати. Ви не хочете, щоб це відповідало. Щоправда, якщо ви дотримувались моєї першої поради, то linux-libc-dev:amd64все одно не потрапите до списку, але все ж. Про структуру номера версії ми знаємо більше, ніж простий факт "є число". Крім того, загалом є хорошою ідеєю цитувати регулярні вирази, просто щоб запобігти можливим неправильним тлумаченням оболонки. Тому я зробив би цю команду egrep

     egrep '[0-9]+\.[0-9]+\.[0-9]+'
  3. Тоді є ця сортування. Чому ви сортуєте? Оскільки ви все-таки збираєтесь видалити всі ядра (крім поточного), чи важливо вам видалити старіші, перш ніж нові? Я не думаю, що це має значення. Або ви це робите лише для того, щоб потім використовувати sedдля "Друку тільки результати, що йдуть після поточного ядра"? Але ІМО це відчуває надто складно. Чому б просто не відфільтрувати результати, що відповідають вашому поточному ядру, як ви вже робите з grep -vбудь-яким, і зробити це? Чесно кажучи, якщо я візьму першу частину вашої команди (з моїми двома попередніми пропозиціями інтегровано), на моїй машині я потрапляю

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | sort -t- -k3,4 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"`
    linux-image-3.8.0-34-generic
    linux-image-3.5.0-44-generic

    Видаляючи те сортування / sed речі, я отримую

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | grep -v -e `uname -r | cut -f1,2 -d"-"`
    linux-image-3.5.0-44-generic
    linux-image-3.8.0-34-generic
    linux-image-extra-3.5.0-44-generic
    linux-image-extra-3.8.0-34-generic

    Отже, ваша більш складна команда насправді пропустила б два пакети на моїй машині, які я хотів би видалити (тепер можливо, що ці linux-image-extra-*речі залежать від linux-image-*речі і тому все-таки видаляться, але це не завадить зробити це явним). У будь-якому випадку я не бачу сенсу вашого сортування; простий, grep -vбез фантазійної попередньої обробки, повинен бути добре, мабуть, навіть краще. Я прихильник принципу KISS. Це вам полегшить зрозуміти чи налагодити пізніше. Крім того, без сортування це трохи ефективніше;)

  4. Це суто естетично, але ви отримаєте той самий вихід із цим трохи коротшим варіантом. :-)

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | grep -v $(uname -r | cut -d- -f-2)
    linux-image-3.5.0-44-generic
    linux-image-3.8.0-34-generic
    linux-image-extra-3.5.0-44-generic
    linux-image-extra-3.8.0-34-generic

Отже, я закінчую більш просту і безпечну команду

$ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | grep -v $(uname -r | cut -d- -f-2) | xargs sudo apt-get -y purge

Оскільки ви насправді хочете очистити свій /bootрозділ, зовсім інший підхід полягатиме в тому, щоб перелічити вміст /boot, використовуйте dpkg -Sдля визначення пакетів, до яких належать окремі файли, відфільтруйте ті, що належать до поточного ядра, та видаліть отримані пакети. Але мені більше подобається ваш підхід, тому що він також знайде застарілі пакети, такі як linux-headers-*, які не встановлюються /boot, а до /usr/src.


Дякую за вашу відповідь @Malte, дякую за ваш внесок. Я вважаю, що два ваші перші кроки є дуже зрозумілими, і вони роблять дійсніше безпечнішим. Однак я вважаю, що ваші два останні кроки ігнорують новіші ядра та також очищають їх. Принаймні, я спробував ваше рішення на моєму сервері, і він би видалив щось небажане.
Алехандро

Це цікаво. Чи можете ви подати мені два виходи, один із командою з моїм третім та четвертим пропозицією, один без них? Плюс вихід uname -r. Для мене це працює чудово. Було б цікаво дізнатися, чому це не працює у вашому випадку.
Malte Skoruppa

1
Я спробував вас пересилити, але я не знайшов жодної адреси електронної пошти, тому я викладу тут свій вихід: hastebin.com/raleyigowe.vhdl uname -r показує, що мій сервер використовує linux-image-3.8.0-34 Річ у тому, що Іноді сервер завантажував новіше ядро, але він ще не встановив його. Ось чому я шукав спосіб видалити лише старі ядра.
Алехандро

Ця команда вибрала файл заголовка для мого поточного ядра, що видається небажаним.
Марк Стосберг

1
@MalteSkoruppa, uname -rвиробляє 4.8.0-36-generic , що не вдається виключити linux-headers-4.8.0-36зі списку.
Марк Стосберг

7

Я написав цей скрипт, який видаляє пакети "linux- *", які мають меншу версію, ніж завантажена в даний час. Я думаю, не потрібно перевіряти стан пакету. Команда запитує підтвердження перед очищенням пакетів. Якщо ви цього не хочете, додайте опцію -y до команди apt-get.

sudo apt-get purge $(dpkg-query -W -f'${Package}\n' 'linux-*' |
sed -nr 's/.*-([0-9]+(\.[0-9]+){2}-[^-]+).*/\1 &/p' | linux-version sort | 
awk '($1==c){exit} {print $2}' c=$(uname -r | cut -f1,2 -d-))

Однак, щоб мати можливість налаштувати кількість запасних ядер, я рекомендую використовувати мій linux-purgeсценарій з --keepопцією. Дивіться тут для отримання додаткової інформації про сценарій.


3

TL; DR: пропустити донизу.

Хоча це трохи довше, хоча. Я розбию його для вас:

  1. dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}'Так, як запропонував Мальте. Перераховує відповідні файли ядра.
  2. egrep '[0-9]+\.[0-9]+\.[0-9]+' Також Malte запропонував як більш безпечний спосіб вибирати лише файли ядра, шукаючи номер версії.
  3. Оскільки ми, можливо, перераховуємо як зображення, так і заголовки пакунків, найменування пакунків може змінюватися, тому у нас є цей непростий спосіб вирішення, необхідний для сортування awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}'. Результатом є новий стовпець з номером версії перед початковою назвою пакета, як нижче:

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}'
    3.11.0-23 linux-headers-3.11.0-23
    3.11.0-23 linux-headers-3.11.0-23-generic
    3.11.0-24 linux-headers-3.11.0-24
    3.11.0-24 linux-headers-3.11.0-24-generic
    3.11.0-26 linux-headers-3.11.0-26
    3.11.0-26 linux-headers-3.11.0-26-generic
    3.11.0-23 linux-image-3.11.0-23-generic
    3.11.0-24 linux-image-3.11.0-24-generic
    3.11.0-26 linux-image-3.11.0-26-generic
    3.8.0-35 linux-image-3.8.0-35-generic
    3.11.0-23 linux-image-extra-3.11.0-23-generic
    3.11.0-24 linux-image-extra-3.11.0-24-generic
    3.11.0-26 linux-image-extra-3.11.0-26-generic
    3.8.0-35 linux-image-extra-3.8.0-35-generic
  4. Тепер ми повинні сортувати список, щоб запобігти видаленню будь-яких нових зображень, ніж ті, що зараз запущені. sort -k1,1 --version-sort -rдаючи нам це:

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}' | sort -k1,1 --version-sort -r
    3.11.0-26 linux-image-extra-3.11.0-26-generic
    3.11.0-26 linux-image-3.11.0-26-generic
    3.11.0-26 linux-headers-3.11.0-26-generic
    3.11.0-26 linux-headers-3.11.0-26
    3.11.0-24 linux-image-extra-3.11.0-24-generic
    3.11.0-24 linux-image-3.11.0-24-generic
    3.11.0-24 linux-headers-3.11.0-24-generic
    3.11.0-24 linux-headers-3.11.0-24
    3.11.0-23 linux-image-extra-3.11.0-23-generic
    3.11.0-23 linux-image-3.11.0-23-generic
    3.11.0-23 linux-headers-3.11.0-23-generic
    3.11.0-23 linux-headers-3.11.0-23
    3.8.0-35 linux-image-extra-3.8.0-35-generic
    3.8.0-35 linux-image-3.8.0-35-generic
  5. Тепер викресліть поточні та новіші файли ядра, що sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"`дають нам це:

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}' | sort -k1,1 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"`
    3.11.0-23 linux-image-extra-3.11.0-23-generic
    3.11.0-23 linux-image-3.11.0-23-generic
    3.11.0-23 linux-headers-3.11.0-23-generic
    3.11.0-23 linux-headers-3.11.0-23
    3.8.0-35 linux-image-extra-3.8.0-35-generic
    3.8.0-35 linux-image-3.8.0-35-generic
  6. Тепер зніміть перший стовпець, який ми додали, awk '{print $2}'щоб отримати саме те, що ми хочемо:

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}' | sort -k1,1 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"` | awk '{print $2}'
    linux-image-extra-3.11.0-23-generic
    linux-image-3.11.0-23-generic
    linux-headers-3.11.0-23-generic
    linux-headers-3.11.0-23
    linux-image-extra-3.8.0-35-generic
    linux-image-3.8.0-35-generic
  7. Тепер ми можемо подати це менеджеру пакунків, щоб автоматично видалити все та налаштувати grub:

    Я рекомендую спочатку зробити сухий пробіг (хоча для ваших цілей сценаріїв це може бути не практично, якщо у вас є велике середовище)

    dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}' | sort -k1,1 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"` | awk '{print $2}' | xargs sudo apt-get --dry-run remove

    Тепер, якщо все виглядає добре, продовжуйте і видаляйте його за допомогою:

    dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}' | sort -k1,1 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"` | awk '{print $2}' | xargs sudo apt-get -y purge

Знову ж таки, вся суть цього "однолінійного" полягає в тому, щоб видалити тільки ядра СТАРШЕ, ніж поточно запущене ядро ​​(що залишає будь-які знову встановлені ядра все ще доступними)

Дякую, дайте мені знати, як це працює для вас, і якщо ви могли б це покращити!


Перевірте мою відповідь
jarno

1

Ви можете просто перерахувати каталог / boot, щоб побачити версії ядра, використовувані командою 'ls'. Потім використовуйте 'sudo apt-get -y purge "xxx"', де "xxx" замінюється номером версії, яку потрібно видалити. Слідкуйте за тим, щоб це не версія, яку ви зараз працюєте !!.


1
Вони хотіли однолінійної команди. Вам потрібно більше 1-го рядка
Анвар


0

Швидка відповідь, пояснення на запит:

dpkg -l 'linux-image-[0-9]*' | 
awk -v current="$(uname -r)" '!/^i/ || $2~current {next} {print $2}' |
sed '$d' | 
xargs echo sudo apt-get autoremove

2
Я пропоную (або, якщо ви хочете, попросити) розширити це, щоб включити пояснення. :)
Елія Каган

@EliahKagan, я думаю, що сценарій не має сенсу. Чому пропускати пакети, які не бажано встановлювати? Сценарій може видалити новіші ядра, ніж поточні, або зберегти старіші за sed '$d'командою. Сценарій не видаляє жодних пакетів linux-заголовків чи інших пакунків, пов’язаних з пакетами ядра, які потрібно видалити, до того ж він не видаляє конфігураційні файли пакетів. Я б рекомендував натомість використовувати свою відповідь.
jarno

@EliahKagan Actally сценарій не видаляє жодних пакетів, але друкує (за echo) apt-getкоманду, яку можна було запустити.
jarno

0

Я дуже втомився від усієї цієї зайвої складності і створив пакет Python, який робить однолінійний тривіальним:

ubuntu-old-kernel-cleanup | xargs sudo apt-get -y purge

Встановіть його за допомогою

sudo pip install git+http://github.com/mrts/ubuntu-old-kernel-cleanup.git

Детальніше дивіться на https://github.com/mrts/ubuntu-old-kernel-cleanup .

Сподіваюся, що це допомагає і іншим.


Пробував це, але я отримую помилку: "ubuntu-old-kernel-cleanup: команда не знайдена"
Грант

Тоді він не знаходиться у вашому виконуваному шляху пошуку. Ви встановили це, sudo pip install ...як описано вище? sudoнасправді важливо, інакше pipбуде встановлено його в деякому каталозі користувача, і оболонка може не шукати в цьому каталозі виконувані файли.
мрц

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

Працює весь час, і навіть ubuntu 17.10


Для мене це намагається зняти linux-libc-dev:amd64, що є небажаним.
Malte Skoruppa
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.