SSD Nodes Learn Hosting plans →
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-08-25

تثبيت نواة VPS التي سيقلع بها في المرة التالية

لا يعمل GRUB_DEFAULT على صورة Ubuntu السحابية. تعرّف إلى إدخالات القائمة الفعلية، ثم ثبّت إقلاع النواة التالية بأمان وتجنب الحاجة إلى وحدة إنقاذ.

ما الذي يحدد النواة التي يقلع بها VPS

يحدد ملف واحد مُولَّد النواة التي سيقلع بها VPS في المرة التالية، وهو /boot/grub/grub.cfg. لا تعدّل هذا الملف مباشرة. عدّل ملفات الإدخال الخاصة به ثم أعد توليده. في صورة Ubuntu السحابية، يأتي أحد ملفات الإدخال من مورّد الصورة. وقد يجعل هذا الملف اختياراً من القائمة غير مؤثر. لذلك لا يغيّر تنفيذ GRUB_DEFAULT=1 ثم update-grub شيئاً على خادم مستأجر، بينما تنجح الخطوتان نفسهما عند تثبيت النظام على حاسوب محمول.

نفّذ العمل بالترتيب التالي. تأكد أولاً من أن اختيار النواة متاح لك. اقرأ كل ملفات الإدخال، بما فيها الملفات التي أضافها المورّد. اقرأ الناتج المُولَّد واحسب عدد الإدخالات الموجودة فيه فعلياً. بعد ذلك فقط اختر طريقة تثبيت النواة. إذا أخطأت في ذلك على جهاز لا تصل إليه إلا عبر SSH، فقد تحتاج إلى وحدة تحكم للإنقاذ. لذلك ستجد أكثر الخيارات أماناً في نهاية هذه الصفحة، وغالباً ما تكون هي الخيارات الصحيحة.

تحقق أولاً من أن النواة تخصك ويمكن تثبيتها

uname -r
systemd-detect-virt
ls -1 /boot/vmlinuz-*

إن عرض systemd-detect-virt أو kvm أو qemu أو xen يعني أنك تشغّل نواتك الخاصة، وأن كل ما يلي ينطبق عليك. أما عرض lxc أو openvz فيعني أن خادمك يشارك نواة المضيف، ولذلك لا يوجد محمّل إقلاع يخصك ولا شيء يمكنك تثبيته. في هذه الحالة، يعرض uname -r إصداراً لا يظهر في /boot/vmlinuz-* على الإطلاق، لأن النواة قيد التشغيل تخص المضيف، ولا يمكن لأي إعداد على قرصك تغييرها.

يمثل ls -1 /boot/vmlinuz-* القائمة الفعلية للنوى التي يمكنك الاختيار بينها. إذا احتوت القائمة على سطر واحد، فهذا يعني أن النواة السابقة حُذفت بالفعل، ولا يمكن لأي إعداد في محمّل الإقلاع استعادتها. يحدث ذلك عادةً أثناء تنفيذ autoremove، ومن المفيد فهمه قبل أن تنظف النوى القديمة على Ubuntu في خادم مهم لديك.

الملف الذي تعدّله ليس الملف الذي يقرأه GRUB

يحتوي /etc/default/grub على تعيينات متغيرات shell عادية. وهو ملف إدخال. أما /boot/grub/grub.cfg فهو ملف الإخراج، ويبدأ بـ# DO NOT EDIT THIS FILE والسبب. يختفي كل ما تكتبه في ملف الإخراج عند تثبيت حزمة kernel أو إزالتها، لأن نصوص الحزمة تعيد إنشاءه.

cat /usr/sbin/update-grub

update-grub هو غلاف. ويشغّل grub-mkconfig -o /boot/grub/grub.cfg، الذي يقرأ المتغيرات، ويشغّل كل نص في /etc/grub.d/، ثم يكتب النتيجة. أمران، واتجاه واحد: تدخل المدخلات، ويخرج grub.cfg.

What overrides your setting: /etc/default/grub.d

grep -rn '^[^#]' /etc/default/grub /etc/default/grub.d/

The second path is the part people miss. grub-mkconfig sources /etc/default/grub first, then every *.cfg file in /etc/default/grub.d/ in glob order. Read the code that does it:

grep -n 'default/grub' /usr/sbin/grub-mkconfig

Sourcing is plain shell, so the last assignment wins. Ubuntu cloud images ship files in that directory, and they set things like the timeout and the kernel command line after your file has already been read. Your GRUB_TIMEOUT=10 in /etc/default/grub is overwritten a moment later by a vendor file that sets it to 0. The grep above prints the exact assignments on your image, so read those rather than trusting this sentence.

The practical rule that follows: put your own settings in a file that sorts last, such as /etc/default/grub.d/99-local.cfg, instead of editing /etc/default/grub. Then nothing shipped by the image can land after you.

لماذا يجعل GRUB_FORCE_PARTUUID اختيار القائمة غير ذي صلة

grep -rn GRUB_FORCE_PARTUUID /etc/default/grub /etc/default/grub.d/
grep -n GRUB_FORCE_PARTUUID /etc/grub.d/10_linux
sudo grep -n 'root=PARTUUID' /boot/grub/grub.cfg

يخبر GRUB_FORCE_PARTUUID المُولِّد بالعثور على نظام الملفات الجذر باستخدام UUID للقسم، ويُكتب ذلك مباشرةً في سطر أوامر النواة بصيغة root=PARTUUID=...، بدلاً من البحث عن UUID لنظام الملفات أثناء الإقلاع. يضبطه مورّد الصورة لأن ذلك يتيح لصورة قرص واحدة الإقلاع بشكل موثوق على أجهزة لم تُبنَ الصورة عليها. يوضح أمر grep الثاني الشيفرة التي تتعامل مع المتغير في /etc/grub.d/10_linux. يوجد هذا البرنامج النصي على قرصك، ولذلك فهو المرجع المعتمد لتحديد ما تفعله صورتك.

النتيجة هي المهمة هنا: في هذا المسار، ينشئ المُولِّد إدخال إقلاع مباشرًا بدلاً من قائمة كاملة بالنوى المثبّتة. احسب عدد الإدخالات الناتجة.

sudo grep -cE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg
sudo grep -nE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg

إذا كان العدد 1، فلا يوجد إدخال ثانٍ يمكن اختياره، ولذلك يشير GRUB_DEFAULT=1 إلى إدخال غير موجود. لا يستطيع GRUB حل هذا المرجع، فيقلع من الإدخال الأول، وهو النواة الجديدة التي كنت تحاول تجنبها. ولا يساعد grub-set-default أيضاً، لأن الإعداد الافتراضي ليس موضع الخلل. فالقائمة التي تحاول الاختيار منها لم تُنشأ أصلاً.

لاستعادة قائمة كاملة، انقل ملف المورّد إلى مكان آخر، ثم اعرض النتيجة المتوقعة قبل اعتمادها. يؤدي grub-mkconfig من دون -o إلى الكتابة في الإخراج القياسي، ولا يغيّر أي شيء على القرص.

sudo grub-mkconfig 2>/dev/null | grep -cE '^\s*(menuentry|submenu) '
sudo mkdir -p /root/grub-backup
sudo mv /etc/default/grub.d/<the file your grep named> /root/grub-backup/
sudo grub-mkconfig 2>/dev/null | grep -cE '^\s*(menuentry|submenu) '

إذا ارتفع العدد من 1 إلى عدة إدخالات، فهذا يعني أن الإدخالات تظهر بعد إزالة الفرض. لم تُكتب أي تغييرات بعد. أعد الملف إلى مكانه إذا لم يكن العدد الثاني مناسباً، لأن PARTUUID المفروض هو الطريقة التي تحدد بها صورة المزوّد نظام الملفات الجذر، وإزالته تنقل الجهاز إلى مسار البحث بدلاً من ذلك. أنشئ snapshot قبل تشغيل update-grub فعلياً.

إذا كان هدفك الوحيد هو تجاوز نواة معطّلة واحدة، فتوقف هنا واستخدم الخيارات الأكثر أماناً أدناه. إن إعادة إنشاء قائمة الإقلاع على خادم بعيد لتجاوز ترقية واحدة تنطوي على مخاطر أكبر من المشكلة نفسها.

لماذا يُعد تثبيت أرقام الإدخالات خياراً خاطئاً

يقبل GRUB_DEFAULT رقماً أو عنواناً أو معرّفاً. تبدأ أرقام الإدخالات ذات المستوى الأعلى من 0. ويُستخدم > فاصلاً للإدخال المتداخل، لذا يعني GRUB_DEFAULT="1>2" الإدخال ذا الفهرس 2 داخل القائمة الفرعية ذات الفهرس 1.

تتغير الفهارس. يعرض 10_linux نوى kernel بترتيب يبدأ بالأحدث، لذا يؤدي تثبيت kernel إلى دفع كل إدخال أقدم إلى الأسفل بمقدار واحد، بينما يؤدي حذف kernel إلى رفعها بمقدار واحد. سيظل 1>2 الذي ثبّتَّه بعناية يُحلَّل بنجاح بعد ذلك. لكنه سيشير الآن إلى kernel مختلف. لن يظهر أي خطأ أو تحذير، وستكتشف المشكلة بعد إعادة التشغيل.

لا تتغير المعرّفات، لأن كل واحد منها يتضمن إصدار kernel. اقرأ المعرّفات لديك:

sudo awk -F"'" '/menuentry_id_option/ {print $2, "==>", $4}' /boot/grub/grub.cfg

تجاهل الأسطر الأولى القليلة من الناتج، فهي تمثل المتغير الذي يجري تعريفه في الترويسة. بعد ذلك، يعرض الجانب الأيسر العنوان الذي يراه القارئ، بينما يعرض الجانب الأيمن المعرّف الذي تمرّره إلى الأدوات. بالنسبة إلى إدخال داخل قائمة فرعية، صِل معرّف القائمة الفرعية بمعرّف الإدخال باستخدام >، وبهذا الترتيب تحديداً، كما تفعل الصيغة الرقمية.

إقلاع النواة السابقة مرة واحدة باستخدام grub-reboot

يُعد اختيار الإقلاع لمرة واحدة هو الخيار المناسب على الخادم البعيد، لأنه يلغي نفسه تلقائياً. يكتب grub-reboot القيمة next_entry في /boot/grub/grubenv. يقرأ GRUB هذا المتغير، ويمسحه، ويحفظ القيمة الممسوحة قبل إقلاع أي شيء. لذلك لا تُعاد محاولة إقلاع نواة تتسبب في panic عند الإقلاع التالي. تحصل على محاولة واحدة، ثم تعود الآلة تلقائياً إلى الإعداد الافتراضي المعتاد.

تحقق أولاً من أن الإعداد المُنشأ يقرأ هذا المتغير فعلاً:

sudo grep -n -B2 -A5 'next_entry' /boot/grub/grub.cfg

يجب أن ترى سطراً يحتوي على load_env وكتلة تضبط default من next_entry. إذا لم يعرض grep أي نتيجة، فهذا يعني أن صورة الإقلاع لا تقرأ grubenv عند الإقلاع. عندها سيقبل shell الأمر grub-reboot، ثم سيتجاهله محمّل الإقلاع. هذا هو مسار الإقلاع المباشر المفروض نفسه من القسم السابق، لكنه يظهر هنا في موضع ثانٍ.

sudo grub-reboot '<the identifier you copied>'
sudo grub-editenv list

يجب أن يعرض grub-editenv list الآن سطراً يحتوي على next_entry= بالقيمة نفسها التي مررتها تماماً. افتح وحدة تحكم مزود الخدمة في علامة تبويب بالمتصفح، ثم أعد التشغيل وتحقق من النتيجة.

sudo reboot
uname -r

يعني عرض uname -r للإصدار الأقدم أن التثبيت نجح. أما عرض الإصدار الجديد فيعني إما أن المعرّف لم يُحلّ، أو أن grubenv لا تتم قراءته. وفي كلتا الحالتين تكون الآلة قيد التشغيل، وهذا هو الهدف من استخدام الخيار لمرة واحدة.

اجعل الاختيار ثابتاً باستخدام GRUB_DEFAULT=saved

يجعل GRUB_DEFAULT=saved القيمة الافتراضية مأخوذة من saved_entry في grubenv، وتضبط هذه القيمة باستخدام grub-set-default. وتبقى هذه القيمة بعد تثبيت نوى جديدة، لأن update-grub يعيد كتابة grub.cfg ولا يلمس grubenv.

echo 'GRUB_DEFAULT=saved' | sudo tee /etc/default/grub.d/99-local.cfg
sudo update-grub
sudo grub-set-default '<the identifier you copied>'
sudo grub-editenv list
sudo grep -n 'set default' /boot/grub/grub.cfg

يجب أن يطبع الأمر الأخير set default="${saved_entry}". إذا طبع set default="0"، فهذا يعني أن شيئاً جرى تحميله بعد ملفك أعاد ضبط GRUB_DEFAULT إلى قيمة حرفية. لذلك اعرض /etc/default/grub.d/ مرة أخرى، وتحقق من أن 99-local.cfg يأتي فعلاً في الترتيب الأخير.

GRUB_SAVEDEFAULT=true إعداد مختلف، ومن السهل الخلط بينه وبين الإعداد الحالي. فهو يحفظ النواة التي أقلعت بها للتو باعتبارها القيمة الافتراضية الجديدة، وبذلك تتبع القيمة الافتراضية آخر إقلاع ناجح. على الخادم، يعني ذلك أن إعادة تشغيل غير تفاعلية قد تغيّر اختيارك المثبّت بهدوء. اتركه معطلاً إلا إذا كان هذا هو السلوك المطلوب.

يفشل التثبيت حسب المعرّف في حالة واحدة أيضاً. إذا أزلت النواة التي يشير إليها المعرّف، فلن يعود المعرّف قابلاً للحل، وستعود إلى الإدخال الأول. لذلك ثبّت الحزمة أيضاً، أو امنع إزالة تلك النواة تلقائياً.

إظهار القائمة في وحدة تحكم مزوّد الخدمة

يتطلب الاختيار التفاعلي ظهور القائمة على الشاشة، لكن صور السحابة تخفيها. أضف هذه الإعدادات إلى الملف الذي يأتي أخيراً حسب الترتيب، ثم شغّل sudo update-grub.

GRUB_TIMEOUT=10
GRUB_TIMEOUT_STYLE=menu
GRUB_RECORDFAIL_TIMEOUT=10

لا يعرض GRUB_TIMEOUT_STYLE=hidden مع GRUB_TIMEOUT=0 أي شيء على الإطلاق، لذلك يرى من يراقب وحدة التحكم رسائل النواة تبدأ فوراً، ويستنتج أن محمّل الإقلاع جرى تخطيه. أما GRUB_RECORDFAIL_TIMEOUT فهي مهلة منفصلة تُستخدم بعد إقلاع لم يكتمل. وتضبطها صور السحابة على 0 أيضاً، ولهذا لا يتوقف الخادم الذي فشل إقلاعه للتو ولا ينتظر تدخلك.

إذا كان مزوّد الخدمة يوفّر وحدة تحكم تسلسلية بدلاً من وحدة رسومية، وما زلت لا ترى شيئاً، فإن GRUB يكتب إلى طرفية لا يمكنك رؤيتها. أضف السطرين معاً، لأن الأول يحدد المخرجات، والثاني يضبط المنفذ:

GRUB_TERMINAL="console serial"
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"

تُضاف عشر ثوانٍ إلى كل عملية إقلاع من الآن فصاعداً. أعد ضبط المهلة إلى 0 بعد الانتهاء.

خيارات أكثر أماناً من تعديل محمّل الإقلاع

يُعد تغيير مدخلات محمّل الإقلاع على جهاز لا تصل إليه إلا عبر SSH الخيار الأعلى خطراً في هذه الصفحة. توجد حلول أقل كلفة، وهي تعالج المشكلة الفعلية عادةً.

تثبيت حزم kernel. إذا كان الهدف هو «لا تثبّت لي kernel أحدث»، فأبلغ مدير الحزم بذلك بدلاً من إبلاغ محمّل الإقلاع.

apt list --installed 2>/dev/null | grep -E '^linux-(image|headers|generic|virtual|kvm|aws|azure|gcp|oracle)'
sudo apt-mark hold linux-image-virtual linux-headers-virtual
apt-mark showhold

استخدم الأسماء التي طبعها الأمر الأول، لأن صور cloud تثبّت عادةً نكهة virtual أو kvm بدلاً من generic. إذا ظهر kernel الأحدث تقريباً عند تحديث الصورة وكنت تشتبه في أن الإصدار نفسه تغيّر دون علمك، فهذا لم يحدث، لأن الإصدار الفرعي يضم التحديثات الموجودة لديك مسبقاً في وسائط تثبيت جديدة، ولا يقدّم للخادم الذي تلقى التحديثات شيئاً لم يكن معروضاً له قبل أسابيع. يتجاوز apt upgrade الحزمة المعلّقة، ويعلن ذلك باستخدام The following packages have been kept back:، كما تتجاوزها التحديثات غير التفاعلية في Ubuntu أيضاً. التكلفة حقيقية: يتوقف kernel المعلّق عن تلقي إصلاحات الأمان، لذلك تعامل معه كإيقاف مؤقت محدد بتاريخ، ثم ألغِ التعليق باستخدام sudo apt-mark unhold. إذا كنت تتجنب تحديثات kernel لأن عمليات إعادة التشغيل تسبب توقفاً للخدمة، لا لأن kernel معيناً معطّل، فإن تحديث kernel المباشر على VPS هو الحل المناسب.

أنشئ snapshot قبل الترقية. يستعيد snapshot النظام خلال دقائق، من دون إدخال أوامر في console ومن دون خطر تطبيق تعديل جزئي على محمّل الإقلاع. أنشئ snapshot، ثم نفّذ الترقية، ثم أعد التشغيل وتحقق. إذا تسبب kernel الجديد في مشكلة، فأعد النظام إلى snapshot، وسيكون مسار الإقلاع مطابقاً لما كان عليه تماماً.

استخدم console أو صورة rescue لجهاز متوقف بالفعل. عندما يتعذر على الخادم الإقلاع، لا يكون إعداد محمّل الإقلاع هو المكان الذي تصلح فيه المشكلة. ويُعد مسار الاسترداد هذا إجراءً مستقلاً: ما يجب فعله عندما يتعذر على VPS الإقلاع بعد تحديث kernel.

ما الذي يتعطل، والرسالة التي ستراها

اختفى تعديلك على /boot/grub/grub.cfg. ثُبّتت حزمة نواة أو أزيلت، وشُغِّل البرنامج النصي للصيانة الخاص بها update-grub، ثم أُعيد إنشاء الملف من المدخلات. يحدّد ترويس # DO NOT EDIT THIS FILE موقعي الإدخال. عدّل هذين الموقعين.

grub-editenv: error: environment block too small. الملف /boot/grub/grubenv مفقود أو مبتور. أعد إنشاءه باستخدام sudo grub-editenv /boot/grub/grubenv create، ثم اضبط قيمتك مرة أخرى وتحقق منها باستخدام sudo grub-editenv list.

تتسبب نواة مثبتة في حدوث panic مع VFS: Unable to mount root fs on unknown-block(0,0). يشير الإدخال الذي ثبّتَّه إلى نواة أو initrd لم يعد موجوداً على القرص، ويحدث ذلك عادةً لأن الحزمة أزيلت بينما بقي المعرّف في grubenv. تتمثل الاستعادة في الإقلاع من وحدة التحكم باستخدام إدخال يعمل، ثم مسح القيمة القديمة.

لم يتغير uname -r بعد إعادة تشغيل توقعت أن تغيّره. تحقق من ثلاثة أمور بالترتيب: هل ما زال grub-editenv list يعرض قيمتك أم استُهلكت؛ هل يظهر المعرّف الذي ضبطته في grub.cfg الحالي؛ هل يحتوي grub.cfg على سطر set default يقرأ المتغير الذي ضبطته. يفسّر أحد هذه الأمور الثلاثة المشكلة في كل مرة.

ظهرت القائمة تلقائياً بعد تعطل النظام. يسجّل GRUB فشل الإقلاع في grubenv على شكل recordfail=1، ويفرض ذلك عرض القائمة في الإقلاع التالي حتى يتمكن شخص من التدخل. امسحها باستخدام sudo grub-editenv /boot/grub/grubenv unset recordfail بعد أن يعود الجهاز إلى حالة سليمة.


الجملة الوحيدة التي تستحق الاحتفاظ بها هي: الملف الذي تعدّله ليس الملف الذي يقرأه GRUB، وعلى صورة سحابية تكون الفجوة بينهما هي مصدر الالتباس. اقرأ الإعداد المُنشأ أولاً. تستند كل القرارات في هذه الصفحة إلى محتواه الفعلي.

FAQ

لماذا لا يغيّر GRUB_DEFAULT=1 نواة الإقلاع التي يستخدمها VPS؟

لأن /boot/grub/grub.cfg المُنشأ في صورة Ubuntu السحابية يحتوي غالباً على إدخال إقلاع واحد، لذلك لا يشير الفهرس 1 إلى أي شيء، ويعود GRUB إلى الإدخال الأول. أكّد ذلك باستخدام sudo grep -cE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg. إذا كان العدد 1، فهذا هو السبب. السبب هو GRUB_FORCE_PARTUUID، الذي يضبطه مورّد الصورة في ملف ضمن /etc/default/grub.d/، ما يضع المُنشئ في مسار إقلاع مباشر بدلاً من إنشاء قائمة كاملة بالنوى المثبتة. اعثر على الملف باستخدام grep -rn GRUB_FORCE_PARTUUID /etc/default/grub /etc/default/grub.d/.

كيف أقلع النواة السابقة مرة واحدة فقط؟

شغّل sudo grub-reboot '<identifier>' باستخدام معرّف تنسخه من grub.cfg الخاص بك، ثم أعد التشغيل مع إبقاء وحدة تحكم المزوّد مفتوحة. يمسح GRUB next_entry قبل الإقلاع، لذلك ينطبق الاختيار على محاولة واحدة فقط، ولا يعيد محاولة إقلاع نواة تتسبب في توقف النظام. أكّد تسجيل القيمة باستخدام sudo grub-editenv list. قبل الاعتماد عليها، شغّل sudo grep -n next_entry /boot/grub/grub.cfg، لأن الصورة التي لا تحمّل grubenv في إعداداتها ستتجاهل الأمر من دون إظهار خطأ.

هل ينبغي تثبيت الاختيار بحسب رقم الإدخال أم بحسب المعرّف؟

بحسب المعرّف. أرقام الإدخالات هي مواضع في قائمة يعيد 10_linux بناءها، مع وضع الأحدث أولاً. لذلك يؤدي تثبيت أي نواة أو إزالتها إلى تغيير الأرقام، كما قد يحل 1>2 القديم إلى إدخال حقيقي لكنه خاطئ من دون عرض تحذير. تتضمن المعرّفات إصدار النواة، ولذلك إما أن تطابق النواة المقصودة أو يفشل حلّها. اعرضها باستخدام sudo grep -n menuentry_id_option /boot/grub/grub.cfg، وانسخ السلسلة الموضوعة بين علامتي اقتباس بعد كل سطر إدخال.

هل تثبيت حزمة النواة أكثر أماناً من تغيير محمّل الإقلاع؟

للهدف المعتاد، نعم. يوقف sudo apt-mark hold linux-image-virtual linux-headers-virtual وصول نواة أحدث تماماً، لذلك لا يتغير مسار الإقلاع ولا يوجد ما يمكن أن يخطئ بسببه من وحدة تحكم قد لا تملك الوصول إليها. تحقّق أولاً من أسماء النكهات المثبتة على جهازك باستخدام apt list --installed، ثم تحقّق من التثبيت باستخدام apt-mark showhold. المقابل هو أن النواة المثبتة لا تتلقى إصلاحات أمنية، لذلك حدّد موعد تشغيل sudo apt-mark unhold قبل تنفيذ التثبيت.