Ubuntu VPS पर सही kernel बूट कैसे सेट करें
Ubuntu क्लाउड इमेज पर GRUB_DEFAULT काम नहीं करता है। जानें कि सर्वर पर मौजूद मेनू एंट्रीज को कैसे पढ़ें और बिना रेस्क्यू कंसोल की मदद लिए अगली बूट के लिए सही kernel को कैसे पिन करें।
आपका VPS कौन सा kernel बूट करेगा, यह कैसे तय होता है
आपका VPS अगली बार कौन सा kernel बूट करेगा, यह एक जनरेट की गई फाइल /boot/grub/grub.cfg द्वारा तय होता है। आप उस फाइल को कभी एडिट नहीं करते हैं। आप उसके इनपुट को एडिट करते हैं और उसे फिर से जनरेट करते हैं। Ubuntu क्लाउड इमेज पर, उन इनपुट में से एक इमेज वेंडर की तरफ से आता है, और यह मेनू सिलेक्शन को अप्रासंगिक बना सकता है। यही कारण है कि किराए के सर्वर पर GRUB_DEFAULT=1 के बाद update-grub चलाने से कुछ नहीं बदलता, जबकि लैपटॉप इंस्टॉल पर यही दो स्टेप्स काम करते हैं।
इस क्रम में काम करें। पुष्टि करें कि kernel चुनने का अधिकार आपके पास है। हर इनपुट फाइल को पढ़ें, जिसमें वेंडर द्वारा जोड़ी गई फाइलें भी शामिल हैं। जनरेट किए गए आउटपुट को पढ़ें और गिनें कि उसमें वास्तव में कितनी एंट्रीज हैं। उसके बाद ही पिनिंग (pinning) का तरीका चुनें। यदि आप इसे ऐसी मशीन पर गलत करते हैं जिसे आप केवल SSH के माध्यम से एक्सेस कर सकते हैं, तो आपको रेस्क्यू कंसोल की आवश्यकता पड़ सकती है। इसलिए, सबसे सुरक्षित उत्तर इस पेज के अंत में दिए गए हैं और अक्सर वही सही होते हैं।
सबसे पहले जाँचें कि क्या kernel आपका है जिसे pin किया जा सकता है
uname -r
systemd-detect-virt
ls -1 /boot/vmlinuz-*systemd-detect-virt प्रिंट होने का अर्थ है kvm, qemu या xen कि आप अपना स्वयं का kernel चला रहे हैं और नीचे दी गई सभी बातें लागू होती हैं। lxc या openvz प्रिंट होने का अर्थ है कि आपका सर्वर host के kernel को साझा करता है, इसलिए आपके पास कोई bootloader नहीं है और pin करने के लिए कुछ भी नहीं है। उस स्थिति में uname -r एक ऐसा version दिखाता है जो /boot/vmlinuz-* में बिल्कुल भी दिखाई नहीं देता है, क्योंकि चल रहा kernel host का है और आपकी disk पर कोई भी setting इसे बदल नहीं सकती है।
ls -1 /boot/vmlinuz-* उन kernels की वास्तविक सूची है जिन्हें आप चुन सकते हैं। यदि इसमें केवल एक line है, तो पिछला kernel पहले ही delete हो चुका है, और कोई भी bootloader setting उसे वापस नहीं ला सकती है। ऐसा आमतौर पर autoremove के दौरान होता है, जिसे किसी महत्वपूर्ण सर्वर पर Ubuntu पर पुराने kernels को साफ करने से पहले समझना आवश्यक है।
जिस फाइल को आप एडिट करते हैं, GRUB उसे नहीं पढ़ता है
/etc/default/grub में साधारण shell variable assignments होते हैं। यह एक इनपुट है। /boot/grub/grub.cfg आउटपुट है, और यह # DO NOT EDIT THIS FILE और कारण के साथ शुरू होता है। जब भी कोई kernel package इंस्टॉल या रिमूव किया जाता है, तो आप आउटपुट में जो कुछ भी लिखते हैं वह मिट जाता है, क्योंकि वे पैकेज स्क्रिप्ट्स इसे फिर से जनरेट करती हैं।
cat /usr/sbin/update-grubupdate-grub एक wrapper है। यह grub-mkconfig -o /boot/grub/grub.cfg को चलाता है, जो variables को पढ़ता है, /etc/grub.d/ में मौजूद हर स्क्रिप्ट को रन करता है, और परिणाम लिखता है। दो कमांड्स, एक दिशा: इनपुट अंदर जाते हैं, और grub.cfg बाहर आता है।
आपकी सेटिंग को क्या ओवरराइड करता है: /etc/default/grub.d
grep -rn '^[^#]' /etc/default/grub /etc/default/grub.d/दूसरा पाथ वह हिस्सा है जिसे लोग नजरअंदाज कर देते हैं। grub-mkconfig पहले /etc/default/grub को सोर्स करता है, और फिर /etc/default/grub.d/ में मौजूद हर *.cfg फाइल को ग्लोब ऑर्डर (glob order) में प्रोसेस करता है। इसे करने वाले कोड को पढ़ें:
grep -n 'default/grub' /usr/sbin/grub-mkconfigसोर्सिंग एक साधारण शेल प्रक्रिया है, इसलिए जो असाइनमेंट अंत में होता है, वही प्रभावी रहता है। Ubuntu क्लाउड इमेजेस उस डायरेक्टरी में फाइलें शिप करती हैं, और वे आपकी फाइल पढ़े जाने के बाद टाइमआउट और कर्नल कमांड लाइन जैसी चीजों को सेट कर देती हैं। आपकी फाइल /etc/default/grub में मौजूद GRUB_TIMEOUT=10 को एक वेंडर फाइल द्वारा तुरंत ओवरराइट कर दिया जाता है, जो इसे 0 पर सेट कर देती है। ऊपर दिया गया grep कमांड आपकी इमेज पर मौजूद सटीक असाइनमेंट्स को प्रिंट करता है, इसलिए इस वाक्य पर भरोसा करने के बजाय उन्हें पढ़ें।
इसका व्यावहारिक नियम यह है: अपनी सेटिंग्स को ऐसी फाइल में रखें जो अंत में सॉर्ट होती हो, जैसे कि /etc/default/grub.d/99-local.cfg, न कि /etc/default/grub को एडिट करें। इससे इमेज द्वारा शिप की गई कोई भी फाइल आपके बाद रन नहीं हो पाएगी।
GRUB_FORCE_PARTUUID menu selection को अप्रासंगिक क्यों बनाता है
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.cfgGRUB_FORCE_PARTUUID जनरेटर को यह निर्देश देता है कि वह बूट होते समय filesystem UUID खोजने के बजाय, partition UUID द्वारा root filesystem को ढूंढे और उसे सीधे kernel command line पर root=PARTUUID=... के रूप में लिखे। इमेज वेंडर इसे इसलिए सेट करता है ताकि एक ही disk image उन हार्डवेयर पर भी भरोसेमंद तरीके से बूट हो सके जिन पर उसे नहीं बनाया गया था। दूसरा grep आपको वह कोड दिखाता है जो /etc/grub.d/10_linux में इस वेरिएबल पर काम करता है। वह स्क्रिप्ट आपकी अपनी डिस्क पर होती है, और वही यह तय करती है कि आपकी इमेज क्या करती है।
इसका परिणाम ही यहाँ महत्वपूर्ण है: उस पाथ पर जनरेटर इंस्टॉल किए गए kernels की पूरी सूची के बजाय एक सीधा बूट एंट्री लिखता है। गणना करें कि अंत में आपके पास क्या बचा है।
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 इसे हल (resolve) नहीं कर सकता, इसलिए यह पहली एंट्री को बूट करता है, जो कि वह नया kernel है जिससे आप बचना चाह रहे थे। grub-set-default भी मदद नहीं करता, क्योंकि डिफ़ॉल्ट सेटिंग समस्या का कारण नहीं है। वह मेनू जिसे आप चुनने का प्रयास कर रहे हैं, वह कभी जनरेट ही नहीं हुआ था।
पूरा मेनू वापस पाने के लिए, वेंडर फ़ाइल को हटा दें और उसे लागू करने से पहले परिणाम का पूर्वावलोकन (preview) करें। -o के बिना grub-mkconfig का उपयोग करने पर आउटपुट standard output पर लिखा जाता है और डिस्क पर कुछ भी नहीं बदलता है।
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 से बढ़कर कई हो जाती है, तो इसका मतलब है कि forcing हटते ही एंट्रीज़ दिखाई देने लगती हैं। अभी तक कुछ भी लिखा नहीं गया है। यदि दूसरी गिनती सही नहीं दिख रही है, तो फ़ाइल को वापस अपनी जगह रख दें, क्योंकि forced PARTUUID ही वह तरीका है जिससे आपके प्रदाता की इमेज अपने root filesystem को लोकेट करती है, और इसे हटाने से मशीन search path पर चली जाती है। update-grub को वास्तव में चलाने से पहले एक snapshot लें।
यदि आपका एकमात्र लक्ष्य एक खराब kernel से बचना है, तो यहीं रुक जाएं और नीचे दिए गए सुरक्षित विकल्पों का उपयोग करें। एक सिंगल अपग्रेड से बचने के लिए रिमोट सर्वर पर बूट मेनू को फिर से बनाना, समस्या की तुलना में अधिक जोखिम भरा है।
एंट्री नंबर को पिन करना गलत क्यों है
GRUB_DEFAULT एक नंबर, एक शीर्षक या एक आइडेंटिफायर स्वीकार करता है। नंबर 0 से शुरू होकर टॉप-लेवल एंट्रीज की गिनती करते हैं। एक नेस्टेड एंट्री > को सेपरेटर के रूप में उपयोग करती है, इसलिए GRUB_DEFAULT="1>2" का अर्थ है इंडेक्स 1 वाले सबमेनू के अंदर इंडेक्स 2 पर मौजूद एंट्री।
इंडेक्स बदलते रहते हैं। 10_linux कर्नल्स को सबसे नए से पुराने के क्रम में लिस्ट करता है, इसलिए नया कर्नल इंस्टॉल करने पर हर पुरानी एंट्री एक स्थान नीचे खिसक जाती है, और कर्नल हटाने पर वे ऊपर आ जाती हैं। आपकी सावधानीपूर्वक सेट की गई 1>2 उसके बाद भी रिजॉल्व होती है। अब वह एक अलग कर्नल को दर्शाती है। कोई एरर नहीं आता, कोई चेतावनी नहीं मिलती, और आपको इसके बारे में रीबूट के बाद पता चलता है।
आइडेंटिफायर नहीं बदलते, क्योंकि प्रत्येक में कर्नल वर्जन शामिल होता है। अपना आइडेंटिफायर यहाँ पढ़ें:
sudo awk -F"'" '/menuentry_id_option/ {print $2, "==>", $4}' /boot/grub/grub.cfgआउटपुट की पहली कुछ लाइनों को अनदेखा करें, जो हेडर में परिभाषित वेरिएबल हैं। उसके बाद, बाईं ओर वह शीर्षक है जिसे यूजर देखता है और दाईं ओर वह आइडेंटिफायर है जिसे आप टूल्स को पास करते हैं। सबमेनू के अंदर की किसी एंट्री के लिए, सबमेनू आइडेंटिफायर और एंट्री आइडेंटिफायर को > के साथ जोड़ें, उसी क्रम में, ठीक वैसे ही जैसे न्यूमेरिक फॉर्म में किया जाता है।
grub-reboot के साथ पिछले kernel को एक बार boot करें
Remote server पर एक बार के लिए selection करना सही कदम है, क्योंकि यह अपने आप वापस सामान्य हो जाता है। grub-reboot, /boot/grub/grubenv में next_entry लिखता है। GRUB उस variable को पढ़ता है, उसे clear करता है, और कुछ भी boot करने से पहले clear की गई value को save कर लेता है। इसलिए यदि kernel panic करता है, तो अगले boot पर उसे दोबारा retry नहीं किया जाता। आपको एक प्रयास मिलता है, जिसके बाद machine अपने आप अपने सामान्य default पर लौट आती है।
सबसे पहले पुष्टि करें कि आपका generated config उस variable को पढ़ता भी है या नहीं:
sudo grep -n -B2 -A5 'next_entry' /boot/grub/grub.cfgआपको एक load_env line और एक ऐसा block चाहिए जो next_entry से default को set करता हो। यदि grep कुछ भी print नहीं करता है, तो आपकी image boot के समय कभी भी grubenv को नहीं पढ़ती है। इसलिए shell पर grub-reboot स्वीकार तो कर लिया जाएगा, लेकिन bootloader द्वारा उसे ignore कर दिया जाएगा। यह वही forced direct boot path है जो पिछले section में दूसरी जगह दिखाई दिया था।
sudo grub-reboot '<the identifier you copied>'
sudo grub-editenv listgrub-editenv list को अब एक next_entry= line print करनी चाहिए जिसमें वही हो जो आपने pass किया था। Browser tab में अपने provider का console खोलें, फिर reboot करें और result की जाँच करें।
sudo rebootuname -runame -r द्वारा पुराने version की रिपोर्ट करने का मतलब है कि pin काम कर गया। नए version की रिपोर्ट करने का मतलब है कि या तो identifier resolve नहीं हुआ या grubenv को पढ़ा नहीं जा रहा है। किसी भी स्थिति में machine चालू है, और one-shot form का उपयोग करने का यही उद्देश्य है।
GRUB_DEFAULT=saved के साथ चयन को स्थायी बनाएँ
GRUB_DEFAULT=saved यह सुनिश्चित करता है कि डिफ़ॉल्ट मान grubenv में स्थित saved_entry से लिया जाए, और आप इस मान को grub-set-default के साथ सेट करते हैं। यह kernel install के बाद भी बना रहता है, क्योंकि 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अंतिम command को set default="${saved_entry}" प्रिंट करना चाहिए। यदि यह set default="0" प्रिंट करता है, तो आपकी फ़ाइल के बाद किसी अन्य स्रोत ने GRUB_DEFAULT को वापस एक literal मान पर सेट कर दिया है। इसलिए /etc/default/grub.d/ को फिर से सूचीबद्ध करें और जाँचें कि 99-local.cfg वास्तव में अंत में है या नहीं।
GRUB_SAVEDEFAULT=true एक अलग सेटिंग है और इसे अक्सर इसके साथ भ्रमित कर दिया जाता है। यह उस kernel को नया डिफ़ॉल्ट बना देता है जिसे आपने अभी boot किया है, इसलिए डिफ़ॉल्ट मान अंतिम सफल boot का अनुसरण करता है। सर्वर पर इसका अर्थ यह है कि एक unattended reboot चुपचाप आपके पिन (pin) को बदल सकता है। जब तक आपको यही परिणाम न चाहिए हो, इसे बंद रखें।
identifier द्वारा पिन (pin) करना एक स्थिति में विफल हो सकता है। यदि आप उस kernel को हटा देते हैं जिसका नाम इसमें दिया गया है, तो identifier resolve होना बंद हो जाएगा, जिससे आप वापस पहली entry पर आ जाएंगे। इसलिए package को hold करें, या उस kernel को autoremove से बाहर रखें।
प्रोवाइडर कंसोल पर मेनू प्राप्त करना
इंटरैक्टिव रूप से चयन करने के लिए स्क्रीन पर मेनू का होना आवश्यक है, और क्लाउड इमेज इसे छिपा देती हैं। इन्हें उस फाइल में डालें जो सबसे अंत में सॉर्ट होती है, फिर sudo update-grub चलाएं।
GRUB_TIMEOUT=10
GRUB_TIMEOUT_STYLE=menu
GRUB_RECORDFAIL_TIMEOUT=10GRUB_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 के माध्यम से एक्सेस की जाने वाली मशीन पर बूटलोडर इनपुट बदलना इस पेज का सबसे जोखिम भरा विकल्प है। इसके सस्ते समाधान मौजूद हैं, और वे आमतौर पर वास्तविक समस्या का समाधान कर देते हैं।
कर्नेल पैकेज को होल्ड (hold) करें। यदि आपका लक्ष्य "मुझे नया कर्नेल न दें" है, तो यह बात बूटलोडर के बजाय पैकेज मैनेजर को बताएं।
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पहले कमांड द्वारा प्रिंट किए गए नामों का ही उपयोग करें, क्योंकि क्लाउड इमेजेस आमतौर पर generic के बजाय virtual या kvm फ्लेवर इंस्टॉल करती हैं। यदि नया कर्नेल इमेज रिफ्रेश के दौरान आया है और आपको संदेह है कि रिलीज बदल गई है, तो ऐसा नहीं है, क्योंकि पॉइंट रिलीज वे अपडेट होते हैं जो आपको पहले ही मिल चुके होते हैं और उन्हें नई इंस्टॉलेशन मीडिया में शामिल कर दिया जाता है और यह किसी पहले से पैच किए गए सर्वर को कुछ भी नया नहीं देता जो उसे हफ्तों पहले पेश न किया गया हो। एक होल्ड किए गए पैकेज को apt upgrade द्वारा छोड़ दिया जाता है, जो इसे The following packages have been kept back: के साथ घोषित करता है, और इसे Ubuntu पर अनअटेंडेड अपग्रेड द्वारा भी छोड़ दिया जाता है। इसकी कीमत चुकानी पड़ती है: एक होल्ड किया गया कर्नेल सुरक्षा फिक्स प्राप्त करना बंद कर देता है, इसलिए इसे एक निश्चित समय के लिए पॉज़ (pause) मानें और sudo apt-mark unhold के साथ इसे रिलीज करें। यदि आप कर्नेल अपडेट से इसलिए बच रहे हैं क्योंकि रीबूट से डाउनटाइम होता है, न कि इसलिए कि कोई कर्नेल खराब है, तो VPS पर लाइव कर्नेल पैचिंग इसका समाधान है।
अपग्रेड से पहले स्नैपशॉट लें। एक स्नैपशॉट मिनटों में रिस्टोर हो जाता है, जिसमें कंसोल पर टाइपिंग की आवश्यकता नहीं होती और बूटलोडर में आधे-अधूरे बदलाव का कोई जोखिम नहीं रहता। स्नैपशॉट लें, अपग्रेड करें, रीबूट करें और सत्यापित करें। यदि नया कर्नेल सही ढंग से काम नहीं करता है, तो रोलबैक करें और बूट पाथ बिल्कुल वैसा ही रहेगा जैसा पहले था।
जो सर्वर पहले से डाउन है, उसके लिए कंसोल या रेस्क्यू इमेज का उपयोग करें। एक बार जब सर्वर बूट नहीं होता है, तो बूटलोडर कॉन्फ़िगरेशन वह जगह नहीं है जहाँ आप इसे ठीक कर सकते हैं, और वह रिकवरी पाथ अपनी एक अलग प्रक्रिया है: कर्नेल अपडेट के बाद VPS बूट न होने पर क्या करें।
क्या खराब होता है और आपको क्या संदेश दिखाई देगा
/boot/grub/grub.cfg में किया गया आपका संपादन गायब हो गया है। एक kernel package इंस्टॉल या रिमूव किया गया था, इसकी maintainer script ने update-grub चलाया, और फाइल को इनपुट से फिर से जनरेट किया गया। # DO NOT EDIT THIS FILE हेडर उन दो इनपुट स्थानों के नाम बताता है। उन्हें संपादित करें।
grub-editenv: error: environment block too small। /boot/grub/grubenv गायब है या अधूरा है। इसे sudo grub-editenv /boot/grub/grubenv create के साथ फिर से बनाएं, फिर अपना मान (value) सेट करें और sudo grub-editenv list के साथ पुष्टि करें।
एक pinned kernel VFS: Unable to mount root fs on unknown-block(0,0) के साथ panic करता है। जिस entry को आपने पिन किया है, वह ऐसे kernel या initrd की ओर इशारा करती है जो अब डिस्क पर नहीं है। ऐसा आमतौर पर तब होता है जब package को रिमूव कर दिया गया हो लेकिन identifier grubenv में बना रहा हो। रिकवरी के लिए एक वर्किंग entry के साथ console boot करें, फिर पुराने मान को हटा दें।
रीबूट के बाद uname -r में कोई बदलाव नहीं हुआ, जिसकी आपको उम्मीद थी। क्रम में तीन चीजों की जाँच करें: क्या grub-editenv list अभी भी आपका मान दिखा रहा है या वह consume हो चुका है; क्या आपके द्वारा सेट किया गया identifier वर्तमान grub.cfg में दिखाई देता है; क्या grub.cfg में set default लाइन है जो आपके द्वारा सेट किए गए variable को पढ़ती है। इन तीनों में से एक कारण हमेशा इसका स्पष्टीकरण देता है।
क्रैश के बाद मेनू अपने आप दिखाई दिया। GRUB एक विफल बूट को grubenv में recordfail=1 के रूप में रिकॉर्ड करता है, और यह अगले बूट पर मेनू को मजबूर करता है ताकि कोई व्यक्ति हस्तक्षेप कर सके। मशीन के ठीक हो जाने पर इसे sudo grub-editenv /boot/grub/grubenv unset recordfail के साथ क्लियर करें।
एक वाक्य जो याद रखने योग्य है: जिस फाइल को आप संपादित करते हैं वह वह फाइल नहीं है जिसे GRUB पढ़ता है, और cloud image पर उनके बीच का अंतर ही भ्रम का कारण है। पहले जनरेट की गई config को पढ़ें। इस पेज पर लिया गया हर निर्णय इस बात पर आधारित है कि वह वास्तव में क्या कहती है।
FAQ
GRUB_DEFAULT=1 मेरे VPS को बूट करने वाले kernel को क्यों नहीं बदलता है?
क्योंकि Ubuntu क्लाउड इमेज पर जनरेट की गई /boot/grub/grub.cfg में अक्सर केवल एक ही बूट एंट्री होती है, इसलिए इंडेक्स 1 का कोई अर्थ नहीं रहता और GRUB वापस पहली एंट्री पर चला जाता है। इसे sudo grep -cE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg के साथ कन्फर्म करें। 1 की संख्या ही इसका उत्तर है। इसका कारण GRUB_FORCE_PARTUUID है, जिसे इमेज वेंडर ने /etc/default/grub.d/ के अंतर्गत एक फाइल में सेट किया है, जो जनरेटर को इंस्टॉल किए गए kernels की पूरी सूची बनाने के बजाय सीधे बूट पाथ पर डाल देता है। grep -rn GRUB_FORCE_PARTUUID /etc/default/grub /etc/default/grub.d/ के साथ उस फाइल को खोजें।
मैं केवल एक बार पिछले kernel को कैसे बूट करूँ?
अपनी grub.cfg से कॉपी किए गए आइडेंटिफायर के साथ sudo grub-reboot '<identifier>' चलाएं, फिर प्रोवाइडर कंसोल को पहले से खोलकर रीबूट करें। GRUB बूट होने से पहले next_entry को क्लियर कर देता है, इसलिए यह विकल्प केवल एक प्रयास पर लागू होता है और यदि kernel पैनिक करता है तो उसे दोबारा प्रयास नहीं किया जाता है। sudo grub-editenv list के साथ कन्फर्म करें कि वैल्यू सेट हो गई है। इस पर भरोसा करने से पहले sudo grep -n next_entry /boot/grub/grub.cfg चलाएं, क्योंकि जिस इमेज की कॉन्फ़िगरेशन grubenv को लोड नहीं करती है, वह बिना किसी एरर के इस कमांड को अनदेखा कर देगी।
क्या मुझे एंट्री नंबर के आधार पर पिन करना चाहिए या आइडेंटिफायर के आधार पर?
आइडेंटिफायर के आधार पर। एंट्री नंबर उस सूची की स्थितियां हैं जिसे 10_linux सबसे नए के आधार पर फिर से बनाता है, इसलिए किसी भी kernel को इंस्टॉल या रिमूव करने से वे बदल जाते हैं, और एक पुराना 1>2 अभी भी एक वास्तविक लेकिन गलत एंट्री पर रिजॉल्व हो जाता है, बिना किसी चेतावनी के। आइडेंटिफायर में kernel वर्जन होता है, इसलिए वे या तो आपके द्वारा चुने गए kernel से मेल खाते हैं या रिजॉल्व होने में विफल हो जाते हैं। उन्हें sudo grep -n menuentry_id_option /boot/grub/grub.cfg के साथ लिस्ट करें और प्रत्येक एंट्री लाइन पर आने वाली कोटेड स्ट्रिंग को कॉपी करें।
क्या बूटलोडर बदलने की तुलना में kernel पैकेज को होल्ड पर रखना अधिक सुरक्षित है?
सामान्य उद्देश्य के लिए, हाँ। sudo apt-mark hold linux-image-virtual linux-headers-virtual किसी नए kernel को आने से रोकता है, इसलिए बूट पाथ कभी नहीं बदलता है और ऐसे कंसोल से कुछ भी गलत होने की संभावना नहीं रहती जो शायद आपके पास न हो। पहले apt list --installed के साथ अपने बॉक्स पर इंस्टॉल किए गए फ्लेवर के नाम चेक करें, और apt-mark showhold के साथ होल्ड को सत्यापित करें। इसका नुकसान यह है कि होल्ड पर रखे गए kernel को कोई सुरक्षा अपडेट नहीं मिलता है, इसलिए होल्ड लगाने से पहले यह तय कर लें कि आप sudo apt-mark unhold कब चलाएंगे।