حذف أنوية Ubuntu القديمة وتحرير مساحة /boot
عندما يمتلئ /boot بحزم linux-image القديمة، يتوقف apt عن إعداد أي شيء. تعرّف إلى الأنوية الآمنة للحذف، واحتفظ بالنواة التي أقلعت بها.
لماذا يتوقف apt عن العمل عندما يمتلئ /boot بالأنوية القديمة
في Ubuntu، يكتب كل تحديث للنواة مجموعة جديدة من الملفات في /boot، ويُبقي الملفات السابقة في مكانها. لذلك يمتلئ قسم /boot الصغير، ولا يستطيع apt إكمال التثبيت. يتطلب الإصلاح خطوتين. حدّد الحزم التي تمثل أنوية على الخادم، وتحقّق من النواة التي أقلعت بها، ثم أزل الحزم الأخرى باستخدام apt autoremove --purge.
ترتيب الخطوات مهم. النواة قيد التشغيل هي الحزمة الوحيدة التي يجب ألا تزيلها. وقد يكون الخادم في حالة تمنع apt من العمل تماماً. ابدأ بالتشخيص.
ما يبدو عليه الفشل فعلياً
يثبّت إصدار kernel ملفين كبيرين في /boot: ملف kernel المضغوط (vmlinuz-<version>) وinitramfs (نظام الملفات الأولي في الذاكرة، initrd.img-<version>، وهو الأرشيف الصغير الذي يفكّه kernel قبل أن يضمّن root الفعلي). يُبنى initramfs على جهازك وقت التثبيت، ولذلك يحتاج التثبيت إلى مساحة حرة، وليس إلى عرض نطاق للتنزيل فقط. عند نفاد المساحة، يفشل البناء ويتسبب ذلك في فشل الحزمة أيضاً.
update-initramfs: Generating /boot/initrd.img-6.8.0-64-generic
gzip: stdout: No space left on device
E: mkinitramfs failure gzip 1
update-initramfs: failed for /boot/initrd.img-6.8.0-64-generic with 1.
dpkg: error processing package linux-image-6.8.0-64-generic (--configure):
installed linux-image-6.8.0-64-generic package post-installation script subprocess returned error exit status 1ستكون سلسلة الإصدار خاصة بك. يأتي اسم أداة الضغط من COMPRESS= في /etc/initramfs-tools/initramfs.conf، ولذلك قد يسمّي image حديث zstd، بينما يسمّي image أقدم gzip. السطران اللذان يحددان هذه المشكلة هما No space left on device وسطر dpkg: error processing package الذي يليه.
بعد ذلك، تبقى الحزمة في حالة إعداد جزئي. تحاول كل عملية apt لاحقة إعدادها من جديد، وتفشل بالطريقة نفسها، وتنتهي بـE: Sub-process /usr/bin/dpkg returned an error code (1). هذه هي النقطة المهمة التي تتجاوز مشكلة مساحة القرص: تعمل unattended-upgrades وفق المؤقت الخاص بها، وتواجه الخطأ نفسه، ثم تتوقف. يبدو الخادم سليماً، لكنه يتوقف بصمت عن تطبيق تصحيحات الأمان. ويعني ذلك أيضاً أن أي تثبيت غير مرتبط تحاول تنفيذه يفشل بالسطر نفسه، وتُلقى المسؤولية على ما كنت تضيفه حينها. لذلك يجدر بك قراءة تثبيت Tailscale الذي يفشل على Ubuntu بوصفه خطأ apt أولاً. إذا فشل apt update قبل وصولك إلى هذه المرحلة، فهذه مشكلة منفصلة، وغالباً ما تكون إدخالاً مكرراً بعد ترحيل مصادر deb822.
تحقق مما إذا كان /boot قسماً منفصلاً
قبل حذف أي شيء، اعرف أولاً المساحة التي ستحررها فعلياً.
findmnt /boot
findmnt -T /boot
df -h /boot /يعرض الأمر الأول سطراً فقط إذا كان /boot نقطة تحميل مستقلة. أما الأمر الثاني فيعرض نتيجة دائماً، ويسمي نظام الملفات الذي يحتوي فعلياً على /boot. إذا سمّيا نظام الملفات نفسه الذي يسمّيه /، فإن /boot ليس سوى مجلد في نظام الملفات الجذر، ولا يمكن أن يمتلئ بشكل مستقل. هذا يعني أن نظام الملفات الجذر ممتلئ، وأن النوى القديمة عامل واحد من عدة عوامل. في هذه الحالة، يفرّغ sudo apt clean ملفات .deb التي جرى تنزيلها ضمن /var/cache/apt/archives، ويوفر مساحة. أما على جهاز يحتوي على قسم /boot فعلي، فلن يحرر apt clean أي مساحة فيه، لأن ذاكرة التخزين المؤقت موجودة في نظام ملفات مختلف.
احصل الآن على الرقم الذي ستعتمد عليه.
df -h /boot
ls -lh /boot/vmlinuz-$(uname -r) /boot/initrd.img-$(uname -r)قارن العمود Avail بحجم هذين الملفين. ملف initrd هو الأكبر. يحتاج تحديث النواة التالي إلى مساحة لزوج آخر بحجم يقارب هذا الحجم. لذلك، إذا كان Avail أصغر من ملف initrd الحالي، فسيفشل التحديث التالي مسبقاً.
تعرّف على النواة التي تعمل بها
uname -r
cat /var/run/reboot-required.pkgsيطبع uname -r سلسلة إصدار النواة الموجودة حالياً في الذاكرة. انسخ هذه السلسلة إلى مكان ما. هذه هي النسخة التي يجب ألّا تلمسها.
لا يوجد الملف الثاني إلا عندما تطلب حزمة برمجية إعادة التشغيل. يعني سطر linux-image فيه أنّ نواة أحدث مثبّتة على القرص لكنها غير مستخدمة، لأن الجهاز لم يُعَد تشغيله منذ تثبيتها. أعد التشغيل قبل التنظيف إذا أمكنك ذلك. يحمي apt النواة قيد التشغيل وأحدث نواة، لذلك يؤدي التنظيف أثناء تشغيل نواة قديمة إلى إبقاء نسخة إضافية مثبّتة لا تحتاج إليها.
سرد حزم النواة وقراءة حالاتها
dpkg --list | grep -E 'linux-(image|modules|headers|tools)' | awk '{print $1, $2}'الحقل الأول هو رمز حالة dpkg. يعني ii أن الحزمة مثبّتة ومهيّأة. ويعني iF أنها مثبّتة لكنها مهيّأة جزئياً، وهذا ما يتركه تحديداً التحديث الفاشل أعلاه. ويعني rc أنها أزيلت مع بقاء إعداداتها على القرص، وهي لا تشغل مساحة في /boot، ويمكن حذفها نهائياً بأمان.
يبيّن الحقل الثاني نوع الحزمة. الاسم الذي يتضمن إصداراً، مثل linux-image-6.8.0-64-generic، يشير إلى نواة محددة. أما الاسم الذي لا يتضمن إصداراً، مثل linux-image-generic أو linux-headers-generic أو linux-generic، فهو حزمة meta. لا تحتوي هذه الحزمة على نواة. وتتمثل وظيفتها بالكامل في الاعتماد على أحدث نواة ذات إصدار، لكي تجلب apt upgrade نوى جديدة. يؤدي حذف حزمة meta إلى إيقاف تلقي الجهاز تحديثات النواة، ولن يظهر أي تحذير بعد ذلك.
تنقسم العائلات على النحو التالي. تحتوي linux-image-* على نواة مضغوطة في /boot. وتحتوي linux-modules-* وlinux-modules-extra-* على برامج التشغيل ضمن /lib/modules. وتحتوي linux-headers-* على ترويسات البناء ضمن /usr/src، ما يعني أن حذف الترويسات نهائياً يحرر مساحة من نظام الملفات الجذر، وليس مساحة /boot. إذا كانت مشكلتك هي امتلاء قسم /boot، فابحث عن حزم صور النواة.
ls -1 /boot/vmlinuz-*
ls -1 /lib/modules/يجب أن تتطابق هاتان القائمتان معاً ومع مخرجات dpkg --list. يشير وجود دليل في /lib/modules بلا حزمة مثبّتة مطابقة إلى بقايا ناتجة عن حذف شخص للملفات يدوياً.
كيفية تحديد apt لنسخ kernels التي يجب الاحتفاظ بها
لن يزيل apt autoremove أي kernel يعتبره محمياً، وتشمل مجموعة kernels المحمية الـkernel الذي تستخدمه حالياً. تغيّرت سياسة الاحتفاظ بين إصدارات Ubuntu، لذلك اقرأها من جهازك بدلاً من الاعتماد على رقم مكتوب في مكان آخر.
apt-config dump | grep -i -e neverautoremove -e versionedkernel
ls -l /etc/apt/apt.conf.d/01autoremove /etc/apt/apt.conf.d/01autoremove-kernelsتمثل APT::NeverAutoRemove قائمة أنماط أسماء الحزم التي يرفض apt autoremove تعديلها. وتمثل APT::VersionedKernelPackages قائمة بادئات الأسماء التي يتعامل معها apt بوصفها حزم kernels ذات إصدارات محددة من الأساس. في الإصدارات التي تنشئ /etc/apt/apt.conf.d/01autoremove-kernels، يعيد /etc/kernel/postinst.d/apt-auto-removal كتابة ذلك الملف في كل مرة تُثبَّت فيها حزمة kernel، لذلك لا يحقق تحريره يدوياً أي فائدة؛ إذ تستبدل عملية تثبيت الـkernel التالية تعديلاتك. في الإصدارات التي لا يوجد فيها الملف، يطبّق apt الحماية نفسها داخلياً. في كلتا الحالتين، يعرض apt-config dump القواعد المطبقة على جهازك، ويكون هذا الناتج هو الإجابة الصحيحة لإصدارك.
التنظيف الآمن للتنفيذ
sudo apt update
sudo apt autoremove --purge --dry-runلا يغيّر --dry-run أي شيء على القرص، ويطبع بالضبط ما ستزيله عملية التنفيذ الفعلية. اقرأ القائمة. هناك أمران يستدعيان التوقف. وجود حزمة meta مثل linux-generic أو linux-image-generic في قائمة الإزالة يعني أن شيئاً ما صنّفها تلقائياً، وإزالتها ستوقف تحديثات kernel لديك. ووجود السلسلة الناتجة من uname -r في قائمة الإزالة يعني أن kernel قيد التشغيل غير محمي، وهذا لا ينبغي أن يحدث ويتطلب التحقيق قبل المتابعة.
إذا بدت القائمة صحيحة، نفّذ الأمر فعلياً.
sudo apt autoremove --purge
df -h /bootيزيل الجزء --purge أيضاً إعدادات الحزمة المتبقية، إلى جانب إزالة الحزمة نفسها. يحرر مساحة إضافية قليلة، ويحافظ على dpkg --list خالياً من تراكم أسطر rc، ما يجعل التدقيق التالي قابلاً للقراءة.
بعد ذلك، تأكد من إعادة بناء قائمة الإقلاع. يؤدي حذف حزمة kernel إلى تشغيل update-grub تلقائياً، لذلك يجب أن تشير القائمة فقط إلى الملفات الموجودة فعلياً.
sudo grep -o 'vmlinuz-[^ ]*' /boot/grub/grub.cfg | sort -u
ls -1 /boot/vmlinuz-*يجب أن يظهر كل إصدار في المخرجات الأولى في المخرجات الثانية. إن وجود إدخال في القائمة يشير إلى ملف لم يعد موجوداً هو ما يحوّل خادماً يعمل إلى خادم يتوقف عند موجه GRUB. وهذا أحد أسباب الوصول إلى VPS لا يقلع بعد تحديث kernel، كما أن إصلاحه من وحدة تحكم الإنقاذ أصعب بكثير من تجنبه هنا.
لماذا لا يزيل apt autoremove أي شيء أحياناً
لا يزيل apt autoremove إلا الحزم المصنّفة تلقائياً، أي الحزم التي ثُبّتت باعتبارها تبعيات لحزمة أخرى. أما نواة ثبّتها بنفسك باستخدام apt install linux-image-6.8.0-40-generic، فتُصنّف يدوياً، ولن يزيلها autoremove مهما أصبحت قديمة.
apt-mark showmanual | grep -E '^linux-'تكون أي نواة ذات إصدار محدد في ذلك الناتج غير مرئية بالنسبة إلى autoremove. أعد تصنيفها، باستخدام سلاسل الإصدارات الظاهرة في قائمتك:
sudo apt-mark auto linux-image-6.8.0-40-generic linux-modules-6.8.0-40-generic
sudo apt autoremove --purge --dry-runاترك حزم meta مصنّفة يدوياً. فهذا هو التصنيف الصحيح لها، لأنك طلبت تثبيتها.
إزالة نواة محددة عمداً
أحياناً تريد إزالة إصدار محدد الآن، بدلاً من الانتظار حتى تسمح السياسة بذلك. حدّد حزمة image ودع apt يتولى بقية العملية.
sudo apt purge linux-image-6.8.0-40-genericيطبع apt قائمة الإزالة قبل تنفيذ أي إجراء، لأن linux-modules-extra-* يعتمد على حزمة image ويجب إزالته في المعاملة نفسها. هذه القائمة المطبوعة هي فحص الأمان الفعلي، ومنها تكتشف إزالة meta package مع الإصدار الذي قصدت إزالته. أجب بـn إذا تضمنت القائمة أي عنصر غير متوقع. بعد ذلك، استخدم sudo apt autoremove --purge لجمع حزم الوحدات والرؤوس التي لم يعد لها سبب للوجود.
لماذا يجب ألا تزيل النواة قيد التشغيل
تستمر النواة الموجودة في الذاكرة في العمل بعد حذف ملفاتها، لذلك لا يبدو أن شيئاً قد تعطل في البداية. لكن ما يتعطل هو كل ما لم تحمّله النواة بعد. يؤدي حذف linux-modules-$(uname -r) إلى حذف /lib/modules/$(uname -r)/، لذلك يفشل تحميل الوحدة التالية:
modprobe: FATAL: Module nf_tables not found in directory /lib/modules/6.8.0-64-genericيفشل إعادة تحميل الجدار الناري بعد ذلك، وكذلك يفشل تركيب نوع من أنظمة الملفات لم تتعامل معه هذه النواة منذ الإقلاع. وفي الوقت نفسه، يصبح /boot/vmlinuz-$(uname -r) غير موجود، لذلك لا تعرض قائمة الإقلاع النواة التي تشغّلها، ويصل النظام إلى مكان آخر عند إعادة التشغيل التالية. يواصل الجهاز تمرير حركة الشبكة، لكنه يصبح غير قابل للإقلاع. طابق uname -r مع قائمة الإزالة في كل مرة.
عندما يمتلئ /boot بدرجة تمنع apt من العمل تماماً
هذه هي الحالة التي تدفع المستخدمين إلى البحث عن هذه الصفحة. يحتاج apt autoremove إلى dpkg لإكمال إعداد حزمة kernel التي أُعدّت جزئياً أولاً. تعيد هذه الخطوة بناء initramfs، وهذا يتطلب مساحة في /boot لا تتوفر فيها مساحة. اكسر هذه الحلقة يدوياً لمرة واحدة.
uname -r
ls -1 /boot/initrd.img-*اختر ملف initrd واحداً لا يطابق إصداره السلسلة النصية التي أعادها uname -r، ثم احذف هذا الملف وحده.
sudo rm /boot/initrd.img-6.8.0-40-generic
sudo apt --fix-broken install
sudo apt autoremove --purge
sudo update-grubلكل سطر سبب. يمثل rm استثناءً مقصوداً، إذ يترك dpkg معتقداً أن ملفاً موجود رغم عدم وجوده فعلياً. يكمل apt --fix-broken install الإعداد الذي فشل بعد أن أصبحت هناك مساحة لـ initramfs. ثم يزيل autoremove --purge الحزمة التي حذفت ملفها، إلى جانب الإصدارات القديمة الأخرى، وبذلك يعيد dpkg إلى التوافق مع محتويات القرص. يعيد update-grub بناء القائمة من الملفات الموجودة فعلياً. لا تعِد التشغيل بين rm وupdate-grub، لأن القائمة قد تشير خلال هذه الفترة إلى الملف الذي حذفته للتو. إذا أبلغ dpkg عن أنه متوقف، فإن sudo dpkg --configure -a ينفذ عملية الإصلاح نفسها التي ينفذها apt --fix-broken install.
المهمة نفسها على أنظمة dnf
إذا كان VPS يعمل بنظام Fedora أو إحدى إصدارات RHEL المعاد بناؤها مثل Rocky Linux، فستكون الآلية معكوسة. تحمي Debian وUbuntu نوى النظام باستخدام قواعد apt autoremove، وتترك عملية التنظيف لك أو لـunattended-upgrades لتشغيلها، بينما تفرض dnf عدداً يُسمى installonly_limit، وتزيل أقدم نواة تلقائياً بمجرد أن يؤدي تثبيت نواة جديدة إلى تجاوز هذا العدد. اقرأ القيمة المطبقة باستخدام grep installonly_limit /etc/dnf/dnf.conf وman 5 dnf.conf، ونظّف التراكم الموجود باستخدام sudo dnf remove --oldinstallonly. وتحمي هذه الأنظمة النواة قيد التشغيل أيضاً. للحصول على مقارنة أوسع بين مديرَي الحزم، راجع مكافئات أوامر dnf وapt.
أوقف تكرار المشكلة
ستفشل عملية التنظيف التي تعتمد على تذكّرك في نهاية المطاف، لذا ضع إعدادها في المكوّن الذي يثبّت kernels. افتح /etc/apt/apt.conf.d/50unattended-upgrades وابحث عن هذه المفاتيح، إذ يحتوي الملف المرفق بها عليها مسبقاً كسطور معلّقة:
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";أزل التعليق عنها بدلاً من إلحاق نسخة ثانية في نهاية الملف. في إعدادات apt، تكون قيمة المفتاح في آخر تعيين هي المعتمدة، لذلك يؤدي التكرار إلى تناقض الملف مع نفسه ويخفي القيمة الفعلية. تحقّق من القيمة التي انتهى إليها المحلّل، وراقب عملية لا تغيّر شيئاً:
apt-config dump | grep -i 'Unattended-Upgrade::Remove'
sudo unattended-upgrade --dry-run --debug
sudo tail -n 40 /var/log/unattended-upgrades/unattended-upgrades.logالسجل هو الدليل. فهو يسجّل كل عملية تشغيل، لذلك يظهر فيه التحديث الذي فشل بسبب نقص المساحة قبل وقت طويل من ملاحظة أن الجهاز متأخر عن تثبيت التحديثات. يشرح التحديثات الأمنية التلقائية على Ubuntu بقية إعدادات ذلك الملف.
قبل تثبيت kernel التالي، هناك رقم واحد يجب التحقق منه، وهو الرقم نفسه الذي تفحصه باستخدام زوج الأوامر الوارد في بداية هذا الدليل:
df -h /boot
ls -lh /boot/initrd.img-$(uname -r)إذا لم تكن قيمة Avail أكبر من ذلك الملف بهامش مريح، فسيفشل kernel التالي تماماً كما هو موضح أعلاه. أصلح المشكلة الآن بدلاً من معالجتها أثناء الترقية. لا يستغرق هذا الفحص أكثر من دقيقة، ويمكن إجراؤه إلى جانب فحوصات صحة القرص على VPS. تزداد أهميته مباشرة قبل ترقية الإصدار، لأن نقل Ubuntu 24.04 إلى 26.04 يثبّت kernel جديداً في مرحلة مبكرة من العملية، وسيرفض do-release-upgrade المتابعة عندما تكون مساحة /boot غير كافية. إذا لم يُعرض هذا التحديث على خادم LTS لديك بعد، فالسبب هو التوقيت وليس وجود عطل، لأن Ubuntu تؤجل ترقيات LTS إلى LTS حتى صدور الإصدار النقطي 26.04.1، ما يمنحك نافذة زمنية واضحة لترتيب /boot أولاً.
FAQ
لماذا يحتفظ Ubuntu بالنوى القديمة بدلاً من حذفها؟
لأن النواة التي تفشل في الإقلاع لا تترك لك خياراً آخر لتحديده. الاحتفاظ بالإصدار السابق يعني إمكانية استرداد النظام من قائمة GRUB بعد تحديث معيب، بدلاً من استخدام وحدة تحكم الإنقاذ لدى المزوّد. لذلك يحمي apt مجموعة من حزم النواة من الإزالة التلقائية، ويشمل دائماً النواة التي تشغّلها حالياً. شغّل apt-config dump | grep -i neverautoremove لرؤية الأنماط الدقيقة التي يحميها إصدارك، لأن السياسة تغيّرت بين الإصدارات.
هل يُعد تشغيل apt autoremove --purge آمناً على خادم إنتاج؟
نعم، بشرط أن تقرأ نتيجة التشغيل التجريبي أولاً. شغّل sudo apt autoremove --purge --dry-run، فهو لا يكتب أي تغييرات، وراجع القائمة المطبوعة. توقّف إذا احتوت على حزمة meta مثل linux-generic أو linux-image-generic، لأن إزالة إحداها توقف تحديثات النواة المستقبلية. وتوقّف أيضاً إذا احتوت على سلسلة الإصدار التي يطبعها uname -r. إذا لم يظهر أيٌّ منهما، فالحزم التي ستُزال هي نوى قديمة وتبعيات يتيمة.
لم يُزل apt autoremove أي شيء وما زال /boot ممتلئاً. ماذا أفعل الآن؟
من شبه المؤكد أن النوى القديمة معلَّمة يدوياً، بينما لا يؤثر autoremove إلا في الحزم المعلَّمة تلقائياً. شغّل apt-mark showmanual | grep -E '^linux-'. كل نواة مذكور إصدارها في القائمة ثُبّتت يدوياً في وقت ما. علّمها تلقائياً باستخدام sudo apt-mark auto linux-image-<version> ثم شغّل التشغيل التجريبي مرة أخرى، أو أزل ذلك الإصدار مباشرة باستخدام sudo apt purge linux-image-<version>.
هل يمكنني حذف الملفات من /boot يدوياً؟
فقط كإجراء استثنائي مقصود، عندما يكون /boot ممتلئاً إلى درجة تمنع apt من إعداد حزمة النواة المعطوبة. احذف ملف initrd.img-<version> واحداً لا يطابق إصداره ناتج uname -r، ثم شغّل فوراً sudo apt --fix-broken install وsudo apt autoremove --purge وsudo update-grub. يؤدي حذف الملفات دون تنفيذ هذه الخطوات اللاحقة إلى إبقاء dpkg مسجلاً لحزم اختفت ملفاتها، كما يترك إدخالات قائمة GRUB تشير إلى ملفات مفقودة، فيفشل الجهاز عند إعادة تشغيله التالية بدلاً من أن يفشل لحظة ارتكاب الخطأ.