הסרת קרנלים ישנים באובונטו

בניגוד להפצות RPM, הפצות על בסיס Debian ובכללם Ubuntu לא מסירות חבילות של קרנלים ישנים, דבר שכבר גרם לי בעיות על /boot מלא ואתחול שכשל בגלל שהחבילה של הקרנל לא הותקנה כמו שצריך. בחיפוש (לא הכי מעמיק) מצאתי הרבה פקודות one-line שבעצם היו אותה פקודה רק בווריאציות שונות (כתיבה טיפה שונה אבל התוצאה זהה) שבעצם הסירו את כל (כולל קרנלים חדשים) החבילות של הקרנלים פרט לקרנל שכרגע בשימוש. לכן חיפשתי משהו שיתאים לדרישה שלי.

הדרישה

הסרה של הקרנלים הישנים

  • עם אפשרות לשמור X עותקים ישנים אחורה (למשל להחזיק תמיד 2 עותקים שעובדים בנוסף לקרנל שרץ)
  • לא להסיר קרנלים חדשים (אחרת מה הטעם, אם אני צריך להתקין אותם שוב)

הסרת כל הקרנלים הישנים עם אפשרות לשמור X גרסאות ישנות – היישום

שורה תחתונה זה מה שיצא לי,

export KEEP_KERNEL=2; dpkg -l 'linux-image*' | awk '/^ii/ { print $2 }' | grep "[0-9]" | awk 'BEGIN{i=1}{print i++, $0}' | grep `uname -r` -B99 | sort -r | tail -n+$(($KEEP_KERNEL+2)) | awk '{print $2}'| xargs apt-get -y --simulate purge
  • הוספתי את המתג  simulate כדי למנוע טעויות של העתק&הדבק – כך שמי שרוצה להריץ את הפקודה יודע מה לעשות.

הסבר

הסקריפט מתחיל מהפקודה dpkg -l ‘linux-image*’ שמקבלת רשימה של כל החבילות שהשם שלהם מתאים ל-REGEX הנ”ל:

# 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          Description
+++-==============================-==============-======================================================
un  linux-image                    <none>         (no description available)
un  linux-image-3.0                <none>         (no description available)
rc  linux-image-3.2.0-23-generic   3.2.0-23.36    Linux kernel image for version 3.2.0 on 64 bit x86 SMP
rc  linux-image-3.2.0-27-generic   3.2.0-27.43    Linux kernel image for version 3.2.0 on 64 bit x86 SMP
rc  linux-image-3.2.0-29-generic   3.2.0-29.46    Linux kernel image for version 3.2.0 on 64 bit x86 SMP
rc  linux-image-3.2.0-30-generic   3.2.0-30.48    Linux kernel image for version 3.2.0 on 64 bit x86 SMP
rc  linux-image-3.2.0-33-generic   3.2.0-33.52    Linux kernel image for version 3.2.0 on 64 bit x86 SMP
rc  linux-image-3.2.0-34-generic   3.2.0-34.53    Linux kernel image for version 3.2.0 on 64 bit x86 SMP
ii  linux-image-3.2.0-37-generic   3.2.0-37.58    Linux kernel image for version 3.2.0 on 64 bit x86 SMP
rc  linux-image-3.2.0-38-generic   3.2.0-38.61    Linux kernel image for version 3.2.0 on 64 bit x86 SMP
ii  linux-image-3.2.0-39-generic   3.2.0-39.62    Linux kernel image for version 3.2.0 on 64 bit x86 SMP
ii  linux-image-3.2.0-40-generic   3.2.0-40.64    Linux kernel image for version 3.2.0 on 64 bit x86 SMP
ii  linux-image-3.2.0-44-generic   3.2.0-44.69    Linux kernel image for version 3.2.0 on 64 bit x86 SMP
ii  linux-image-3.2.0-45-generic   3.2.0-45.70    Linux kernel image for version 3.2.0 on 64 bit x86 SMP
ii  linux-image-server             3.2.0.45.54    Linux kernel image on Server Equipment.

לאחר מכן אנו רוצים לסנן את הרשימה ולברור את החבילות המותקנות על המערכת, זאת אנו עושים ע”י סינון של  כל השורות שמתחילות ב-ii, ומדפיסים רק את שם החבילה

# dpkg -l 'linux-image*' | awk '/^ii/ { print $2 }'
linux-image-3.2.0-37-generic
linux-image-3.2.0-39-generic
linux-image-3.2.0-40-generic
linux-image-3.2.0-44-generic
linux-image-3.2.0-45-generic
linux-image-server

שלב הבא יהיה לסנן עוד טיפה את הרשימה כך שתכיל רק את השמות של החבילות של הקרנלים, במקרה זה פשוט סיננתי את השורות שמכילים מספרים.

# dpkg -l 'linux-image*' | awk '/^ii/ { print $2 }' | grep "[0-9]"
linux-image-3.2.0-37-generic
linux-image-3.2.0-39-generic
linux-image-3.2.0-40-generic
linux-image-3.2.0-44-generic
linux-image-3.2.0-45-generic

אוקי, כאן עשיתי משהו מאוד לא בריא, בגדול ויצאתי מתוך הנחה שהרשימה שאני מקבל ממנהל החבילות תמיד תהיה מסודרת מהקרנל הישן לחדש ולכן לא מיינתי את הרשימה, וכדי למנוע בעיה של מיון בעתיד הוספתי לכל שורה מספר סידורי.

# dpkg -l 'linux-image*' | awk '/^ii/ { print $2 }' | grep "[0-9]" | awk 'BEGIN{i=1}{print i++, $0}'
1 linux-image-3.2.0-37-generic
2 linux-image-3.2.0-39-generic
3 linux-image-3.2.0-40-generic
4 linux-image-3.2.0-44-generic
5 linux-image-3.2.0-45-generic

במקרה שלי אני רץ עם קרנל – linux-image-3.2.0-44-generic, ואני רוצה לקבל רשימה של כל הקרנלים שהם ישנים יותר מהקרנל שאני מריץ, כך שביקשתי למצוא ברשימה את הקרנל שאני מריץ, ואת כל השורות שמגיעות לפניו.

# dpkg -l 'linux-image*' | awk '/^ii/ { print $2 }' | grep "[0-9]" | awk 'BEGIN{i=1}{print i++, $0}' | grep `uname -r` -B99
1 linux-image-3.2.0-37-generic
2 linux-image-3.2.0-39-generic
3 linux-image-3.2.0-40-generic
4 linux-image-3.2.0-44-generic

על פי הדרישה שלי אני רוצה לשמור את הקרנל הקיים, ו-2 גרסאות אחורה – ולכן אני מעוניין להסיר את רק את החבילה linux-image-3.2.0-37-generic. כך שאם אני ממיין את הרשימה הפוך וקופץ 3 שורות, אני אקבל את כל החבילות שאני צריך להסיר, ועל מנת שאוכל לנהל את מספר הגרסאות שאני רוצה להחזיק בצורה פשוטה יותר, השתמשתי במשתנה בתחילת הפקודה.

# export KEEP_KERNEL=2; dpkg -l 'linux-image*' | awk '/^ii/ { print $2 }' | grep "[0-9]" | awk 'BEGIN{i=1}{print i++, $0}' | grep `uname -r` -B99 | sort -r | tail -n+$(($KEEP_KERNEL+2)) | awk '{print $2}'
linux-image-3.2.0-37-generic

כעת מה שנשאר זה להעביר את הרשימה ל-xargs ולתת לה להריץ את הפקודה apt-get purge עם רשימה של כל הקרנלים שאנו רוצים להסיר.

 

 

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *