Cara Tetapkan Kernel Boot VPS Ubuntu dengan Betul
GRUB_DEFAULT tidak berfungsi pada imej awan Ubuntu? Ketahui cara membaca entri menu sebenar dan tetapkan kernel boot tanpa risiko kehilangan akses ke konsol pelayan anda.
Perkara yang menentukan kernel untuk but VPS anda
Kernel yang akan dibut oleh VPS anda seterusnya ditentukan oleh satu fail yang dijana, iaitu /boot/grub/grub.cfg. Anda tidak boleh menyunting fail tersebut secara terus. Anda perlu menyunting inputnya dan menjana semula fail itu. Pada imej awan Ubuntu, salah satu input tersebut datang daripada vendor imej, dan ia boleh menyebabkan pemilihan menu menjadi tidak relevan. Inilah sebabnya mengapa GRUB_DEFAULT=1 diikuti oleh update-grub tidak membawa sebarang perubahan pada pelayan sewaan, sedangkan dua langkah yang sama berfungsi pada pemasangan komputer riba.
Lakukan kerja mengikut urutan ini. Sahkan bahawa anda mempunyai hak untuk memilih kernel. Baca setiap fail input, termasuk fail yang ditambah oleh vendor. Baca output yang dijana dan kira jumlah entri yang terkandung di dalamnya. Hanya selepas itu, pilih kaedah penyematan (pinning). Jika anda melakukan kesilapan pada mesin yang hanya boleh dicapai melalui SSH, anda akan memerlukan konsol pemulihan. Oleh itu, jawapan yang paling selamat berada di penghujung halaman ini dan ia sering kali merupakan pilihan yang tepat.
Pastikan kernel tersebut milik anda sebelum melakukan pinning
uname -r
systemd-detect-virt
ls -1 /boot/vmlinuz-*systemd-detect-virt mencetak kvm, qemu atau xen bermakna anda menjalankan kernel sendiri dan semua perkara di bawah adalah terpakai. Mencetak lxc atau openvz bermakna pelayan anda berkongsi kernel hos, jadi tiada bootloader milik anda dan tiada apa-apa untuk di-pin. Dalam kes tersebut, uname -r melaporkan versi yang tidak muncul langsung dalam /boot/vmlinuz-*, kerana kernel yang sedang berjalan adalah milik hos dan tiada tetapan pada cakera anda boleh mengubahnya.
ls -1 /boot/vmlinuz-* ialah senarai sebenar kernel yang boleh anda pilih. Jika ia mengandungi satu baris, kernel sebelumnya telah pun dipadamkan, dan tiada tetapan bootloader yang boleh mengembalikannya. Perkara itu biasanya berlaku semasa autoremove, yang perlu difahami sebelum anda membersihkan kernel lama pada Ubuntu pada mesin yang penting bagi anda.
Fail yang anda sunting bukanlah fail yang dibaca oleh GRUB
/etc/default/grub mengandungi tugasan pemboleh ubah shell biasa. Ia merupakan input. /boot/grub/grub.cfg ialah output, dan ia bermula dengan # DO NOT EDIT THIS FILE serta sebabnya. Apa-apa sahaja yang anda tulis ke dalam output akan hilang pada kali seterusnya pakej kernel dipasang atau dibuang, kerana skrip pakej tersebut akan menjana semula fail itu.
cat /usr/sbin/update-grubupdate-grub ialah pembalut (wrapper). Ia menjalankan grub-mkconfig -o /boot/grub/grub.cfg, yang membaca pemboleh ubah, menjalankan setiap skrip dalam /etc/grub.d/, dan menulis hasilnya. Dua arahan, satu arah: input dimasukkan, grub.cfg dikeluarkan.
Perkara yang mengatasi tetapan anda: /etc/default/grub.d
grep -rn '^[^#]' /etc/default/grub /etc/default/grub.d/Laluan kedua ialah bahagian yang sering terlepas pandang. grub-mkconfig memuatkan /etc/default/grub terlebih dahulu, kemudian setiap fail *.cfg dalam /etc/default/grub.d/ mengikut susunan glob. Baca kod yang melaksanakannya:
grep -n 'default/grub' /usr/sbin/grub-mkconfigProses memuatkan (sourcing) menggunakan shell biasa, jadi tugasan terakhir yang akan diguna pakai. Imej cloud Ubuntu menyertakan fail dalam direktori tersebut, dan ia menetapkan perkara seperti timeout serta baris arahan kernel selepas fail anda dibaca. GRUB_TIMEOUT=10 anda dalam /etc/default/grub ditimpa sejurus selepas itu oleh fail vendor yang menetapkannya kepada 0. Arahan grep di atas mencetak tugasan sebenar pada imej anda, jadi bacalah maklumat tersebut daripada mempercayai ayat ini.
Peraturan praktikal yang perlu diikuti: letakkan tetapan anda sendiri dalam fail yang disusun paling akhir, seperti /etc/default/grub.d/99-local.cfg, bukannya menyunting /etc/default/grub. Dengan cara ini, tiada apa-apa yang disertakan oleh imej tersebut boleh dilaksanakan selepas anda.
Mengapa GRUB_FORCE_PARTUUID menjadikan pemilihan menu tidak relevan
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 memberitahu penjana untuk mencari sistem fail root mengikut UUID partition, yang ditulis terus pada baris arahan kernel sebagai root=PARTUUID=..., bukannya mencari UUID sistem fail semasa but. Vendor imej menetapkan perkara ini kerana ia menjadikan satu imej cakera boleh but dengan pasti pada perkakasan yang tidak dibina untuknya. Arahan grep kedua menunjukkan kod yang bertindak ke atas pemboleh ubah tersebut, dalam /etc/grub.d/10_linux. Skrip itu berada pada cakera anda sendiri, dan ia merupakan autoriti tentang perkara yang dilakukan oleh imej anda.
Akibatnya adalah perkara yang penting di sini: pada laluan tersebut, penjana menulis entri but terus dan bukannya senarai penuh kernel yang dipasang. Kira jumlah yang anda perolehi akhirnya.
sudo grep -cE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg
sudo grep -nE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfgJika jumlahnya ialah 1, tiada entri kedua untuk dipilih, jadi GRUB_DEFAULT=1 menamakan entri yang tidak wujud. GRUB tidak dapat menyelesaikannya, jadi ia memulakan entri pertama, iaitu kernel baharu yang anda cuba elakkan. grub-set-default juga tidak membantu, kerana lalai (default) bukanlah bahagian yang rosak. Menu yang anda cuba pilih tidak pernah dijana.
Untuk mendapatkan semula menu penuh, alihkan fail vendor ke tepi dan pratonton hasilnya sebelum melakukan perubahan. grub-mkconfig tanpa -o menulis ke output standard dan tidak menyentuh apa-apa pada cakera.
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) 'Jumlah yang melonjak daripada 1 kepada beberapa bermakna entri muncul sebaik sahaja paksaan (forcing) itu tiada. Tiada apa-apa yang telah ditulis lagi. Kembalikan fail tersebut jika jumlah kedua tidak kelihatan betul, kerana PARTUUID yang dipaksa adalah cara imej pembekal anda mencari sistem fail rootnya, dan mengalih keluarnya akan mengalihkan mesin ke laluan carian sebaliknya. Ambil snapshot sebelum anda menjalankan update-grub secara sebenar.
Jika matlamat tunggal anda adalah untuk bertahan daripada satu kernel yang rosak, berhenti di sini dan gunakan pilihan yang lebih selamat di bawah. Membina semula menu but pada pelayan jauh untuk mengelakkan satu naik taraf adalah risiko yang lebih besar daripada masalah itu sendiri.
Mengapa nombor entri bukan cara yang betul untuk melakukan pinning
GRUB_DEFAULT menerima nombor, tajuk, atau pengecam. Nombor mengira entri peringkat atas bermula daripada 0. Entri bersarang menggunakan > sebagai pemisah, jadi GRUB_DEFAULT="1>2" bermaksud entri pada indeks 2 di dalam submenu pada indeks 1.
Indeks boleh berubah. 10_linux menyenaraikan kernel dengan yang terbaharu di atas, jadi memasang kernel akan menolak setiap entri lama ke bawah sebanyak satu kedudukan, dan membuang kernel akan menariknya ke atas. 1>2 anda yang teliti masih akan selesai selepas itu. Ia kini menamakan kernel yang berbeza. Tiada ralat berlaku, tiada amaran diberikan, dan anda hanya akan mengetahuinya selepas but semula.
Pengecam tidak berubah, kerana setiap satunya mengandungi versi kernel. Baca milik anda:
sudo awk -F"'" '/menuentry_id_option/ {print $2, "==>", $4}' /boot/grub/grub.cfgAbaikan beberapa baris pertama output, iaitu pemboleh ubah yang ditakrifkan dalam pengepala. Selepas itu, bahagian kiri ialah tajuk yang dilihat oleh pembaca dan bahagian kanan ialah pengecam yang anda berikan kepada alatan tersebut. Untuk entri di dalam submenu, gabungkan pengecam submenu dan pengecam entri dengan >, mengikut urutan tersebut, tepat seperti bentuk berangka.
But semula kernel sebelumnya sekali sahaja dengan grub-reboot
Pemilihan sekali sahaja adalah langkah yang tepat pada pelayan jauh, kerana ia membatalkan dirinya sendiri. grub-reboot menulis next_entry ke dalam /boot/grub/grubenv. GRUB membaca pemboleh ubah tersebut, mengosongkannya, dan menyimpan nilai yang telah dikosongkan sebelum ia memulakan apa-apa, jadi kernel yang mengalami panik tidak akan dicuba semula pada but seterusnya. Anda mendapat satu percubaan, kemudian mesin akan kembali kepada tetapan lalai asalnya secara automatik.
Pertama, sahkan konfigurasi yang dijana oleh anda membaca pemboleh ubah tersebut:
sudo grep -n -B2 -A5 'next_entry' /boot/grub/grub.cfgAnda mahukan baris load_env dan blok yang menetapkan default daripada next_entry. Jika grep tidak mencetak apa-apa, imej anda tidak pernah membaca grubenv semasa but, jadi grub-reboot akan diterima pada shell dan kemudian diabaikan oleh bootloader. Itu adalah laluan but terus yang sama seperti bahagian sebelumnya yang muncul di tempat kedua.
sudo grub-reboot '<the identifier you copied>'
sudo grub-editenv listgrub-editenv list kini sepatutnya mencetak baris next_entry= yang mengandungi tepat apa yang anda hantar. Buka konsol pembekal anda dalam tab pelayar, kemudian but semula dan semak hasilnya.
sudo rebootuname -runame -r yang melaporkan versi lebih lama bermakna pin tersebut berjaya. Melaporkan versi baharu bermakna sama ada pengecam tidak dapat diselesaikan atau grubenv tidak dibaca, dan mesin tetap hidup dalam kedua-dua keadaan, itulah tujuan menggunakan bentuk sekali sahaja ini.
Jadikan pilihan kekal dengan GRUB_DEFAULT=saved
GRUB_DEFAULT=saved menjadikan nilai lalai diambil daripada saved_entry dalam grubenv, dan anda menetapkan nilai tersebut dengan grub-set-default. Ia kekal selepas pemasangan kernel, kerana update-grub menulis semula grub.cfg dan tidak pernah menyentuh 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.cfgArahan terakhir mesti memaparkan set default="${saved_entry}". Jika ia memaparkan set default="0", sesuatu yang dimuatkan selepas fail anda telah menetapkan semula GRUB_DEFAULT kepada nilai literal, jadi senaraikan /etc/default/grub.d/ sekali lagi dan pastikan 99-local.cfg benar-benar berada di urutan terakhir.
GRUB_SAVEDEFAULT=true ialah tetapan yang berbeza dan mudah dikelirukan dengan tetapan ini. Ia menyimpan apa sahaja yang baru anda but sebagai lalai yang baharu, jadi nilai lalai akan mengikut but berjaya yang terakhir. Pada pelayan, ini bermakna but semula tanpa pengawasan boleh mengubah pin anda secara senyap. Biarkan ia dimatikan kecuali jika itu yang anda mahukan.
Pin mengikut pengecam masih gagal dalam satu keadaan. Buang kernel yang dinamakan olehnya dan pengecam tersebut akan berhenti berfungsi, yang menyebabkan sistem kembali ke entri pertama. Jadi, tahan (hold) pakej tersebut atau pastikan kernel itu tidak termasuk dalam autoremove.
Memaparkan menu pada konsol pembekal
Pemilihan secara interaktif memerlukan menu dipaparkan pada skrin, namun imej awan menyembunyikannya. Masukkan tetapan ini ke dalam fail yang disusun paling akhir, kemudian jalankan sudo update-grub.
GRUB_TIMEOUT=10
GRUB_TIMEOUT_STYLE=menu
GRUB_RECORDFAIL_TIMEOUT=10GRUB_TIMEOUT_STYLE=hidden bersama-sama dengan GRUB_TIMEOUT=0 tidak memaparkan apa-apa, jadi sesiapa yang memantau konsol akan melihat mesej kernel bermula serta-merta dan membuat kesimpulan bahawa bootloader telah dilangkau. GRUB_RECORDFAIL_TIMEOUT ialah tempoh masa tamat (timeout) berasingan yang digunakan selepas proses but yang tidak lengkap, dan imej awan menetapkannya kepada 0. Inilah sebabnya pelayan yang gagal but tetap tidak berhenti dan menunggu anda.
Jika pembekal anda menyediakan konsol bersiri dan bukannya konsol grafik namun anda masih tidak melihat apa-apa, GRUB sedang menulis ke terminal yang tidak dapat anda lihat. Tambahkan kedua-dua baris ini bersama-sama, kerana baris pertama memilih output dan baris kedua mengkonfigurasi port:
GRUB_TERMINAL="console serial"
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"Sepuluh saat akan ditambah pada setiap proses but mulai sekarang. Tetapkan semula tempoh masa tamat kepada 0 sebaik sahaja anda selesai.
Pilihan yang lebih selamat daripada menyunting bootloader
Mengubah input bootloader pada mesin yang hanya dicapai melalui SSH ialah pilihan paling berisiko dalam halaman ini. Terdapat penyelesaian yang lebih murah, dan biasanya ia menyelesaikan masalah sebenar.
Tahan (hold) pakej kernel. Jika matlamatnya adalah "jangan berikan saya kernel yang lebih baharu", nyatakan perkara itu kepada pengurus pakej dan bukannya kepada bootloader.
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 showholdGunakan apa jua nama yang dicetak oleh arahan pertama, kerana imej awan biasanya memasang varian virtual atau kvm dan bukannya generic. Jika kernel yang lebih baharu muncul semasa penyegaran imej dan anda mengesyaki keluaran tersebut berubah tanpa pengetahuan anda, ia sebenarnya tidak berubah, kerana point release ialah kemas kini yang sudah anda miliki yang digabungkan ke dalam media pemasangan baharu dan tidak memberikan apa-apa kepada pelayan yang sudah ditampal (patched) yang tidak ditawarkan beberapa minggu lebih awal. Pakej yang ditahan akan dilangkau oleh apt upgrade, yang akan mengumumkannya dengan The following packages have been kept back:, dan ia juga dilangkau oleh unattended upgrades pada Ubuntu. Kosnya nyata: kernel yang ditahan tidak akan menerima pembetulan keselamatan, jadi anggap ia sebagai jeda yang mempunyai tarikh luput dan lepaskan ia dengan sudo apt-mark unhold. Jika anda mengelakkan kemas kini kernel kerana but semula menyebabkan downtime dan bukannya kerana kernel tersebut bermasalah, live kernel patching pada VPS adalah jawapan bagi masalah itu.
Ambil snapshot sebelum naik taraf. Snapshot boleh dipulihkan dalam beberapa minit, tanpa perlu menaip pada konsol dan tiada risiko perubahan bootloader yang tidak lengkap. Ambil snapshot, naik taraf, but semula, dan sahkan. Jika kernel baharu berkelakuan tidak sepatutnya, buat rollback dan laluan but akan kembali tepat seperti sebelumnya.
Gunakan konsol atau imej pemulihan untuk kotak yang sudah terhenti. Apabila pelayan tidak mahu but, konfigurasi bootloader bukanlah tempat untuk membaikinya, dan laluan pemulihan itu mempunyai prosedurnya sendiri: apa yang perlu dilakukan apabila VPS tidak mahu but selepas kemas kini kernel.
Apa yang rosak, dan mesej yang akan anda lihat
Suntingan anda pada /boot/grub/grub.cfg hilang. Pakej kernel telah dipasang atau dibuang, skrip penyelenggaranya menjalankan update-grub, dan fail tersebut dijana semula daripada input. Pengepala # DO NOT EDIT THIS FILE menamakan dua lokasi input tersebut. Sunting lokasi-lokasi itu.
grub-editenv: error: environment block too small. /boot/grub/grubenv hilang atau terpotong. Cipta semula dengan sudo grub-editenv /boot/grub/grubenv create, kemudian tetapkan nilai anda semula dan sahkan dengan sudo grub-editenv list.
Kernel yang dipin (pinned) mengalami panik dengan VFS: Unable to mount root fs on unknown-block(0,0). Entri yang anda pin merujuk kepada kernel atau initrd yang tidak lagi berada pada cakera, biasanya kerana pakej tersebut telah dibuang manakala pengecamnya kekal dalam grubenv. Pemulihan dilakukan dengan but konsol menggunakan entri yang berfungsi, kemudian membersihkan nilai yang lapuk itu.
uname -r tidak berubah selepas but semula yang anda jangkakan akan mengubahnya. Semak tiga perkara mengikut urutan: adakah grub-editenv list masih menunjukkan nilai anda atau adakah ia telah digunakan; adakah pengecam yang anda tetapkan muncul dalam grub.cfg semasa; adakah grub.cfg mengandungi baris set default yang membaca pemboleh ubah yang anda tetapkan. Salah satu daripada tiga perkara ini sentiasa menjadi puncanya.
Menu muncul dengan sendirinya selepas kegagalan sistem (crash). GRUB merekodkan but yang gagal dalam grubenv sebagai recordfail=1, dan ini memaksa menu muncul pada but seterusnya supaya manusia boleh campur tangan. Kosongkan ia dengan sudo grub-editenv /boot/grub/grubenv unset recordfail sebaik sahaja mesin kembali sihat.
Satu ayat yang perlu diingat: fail yang anda sunting bukanlah fail yang dibaca oleh GRUB, dan pada imej awan, jurang antara kedua-duanya adalah punca kekeliruan. Baca konfigurasi yang dijana terlebih dahulu. Setiap keputusan pada halaman ini adalah berdasarkan apa yang tertulis di dalamnya.
FAQ
Mengapa GRUB_DEFAULT=1 tidak menukar kernel yang digunakan oleh VPS saya semasa but?
Kerana pada imej awan Ubuntu, /boot/grub/grub.cfg yang dijana selalunya hanya mengandungi satu entri but, jadi indeks 1 tidak merujuk kepada apa-apa dan GRUB akan kembali kepada entri pertama. Sahkan perkara ini dengan sudo grep -cE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg. Jumlah kiraan 1 adalah puncanya. Sebabnya ialah GRUB_FORCE_PARTUUID, yang ditetapkan oleh vendor imej dalam fail di bawah /etc/default/grub.d/, yang meletakkan penjana pada laluan but terus dan bukannya membina senarai penuh kernel yang dipasang. Cari fail tersebut dengan grep -rn GRUB_FORCE_PARTUUID /etc/default/grub /etc/default/grub.d/.
Bagaimanakah cara untuk but menggunakan kernel sebelumnya hanya untuk sekali sahaja?
Jalankan sudo grub-reboot '<identifier>' dengan pengecam yang disalin daripada grub.cfg anda sendiri, kemudian but semula dengan konsol pembekal sudah dibuka. GRUB akan memadamkan next_entry sebelum ia but, jadi pilihan tersebut hanya terpakai untuk satu percubaan sahaja dan kernel yang mengalami panik tidak akan dicuba semula. Sahkan nilai tersebut telah ditetapkan dengan sudo grub-editenv list. Sebelum bergantung kepadanya, jalankan sudo grep -n next_entry /boot/grub/grub.cfg, kerana imej yang konfigurasinya tidak memuatkan grubenv akan mengabaikan arahan tersebut tanpa sebarang ralat.
Adakah saya perlu menetapkan (pin) mengikut nombor entri atau pengecam?
Gunakan pengecam. Nombor entri adalah kedudukan dalam senarai yang disusun semula oleh 10_linux dengan yang terbaharu di atas, jadi memasang atau membuang mana-mana kernel akan mengubah kedudukannya, dan 1>2 yang lama masih akan merujuk kepada entri yang sah tetapi salah tanpa sebarang amaran dicetak. Pengecam mengandungi versi kernel, jadi ia sama ada sepadan dengan kernel yang anda maksudkan atau gagal untuk diselesaikan. Senaraikan ia dengan sudo grep -n menuentry_id_option /boot/grub/grub.cfg dan salin rentetan bertanda petikan yang muncul pada setiap baris entri.
Adakah menahan (hold) pakej kernel lebih selamat daripada menukar bootloader?
Untuk tujuan biasa, ya. sudo apt-mark hold linux-image-virtual linux-headers-virtual menghalang kernel yang lebih baharu daripada dipasang, jadi laluan but tidak pernah berubah dan tiada risiko kesilapan daripada konsol yang mungkin tidak anda miliki. Semak nama varian yang dipasang pada pelayan anda sendiri terlebih dahulu dengan apt list --installed, dan sahkan status tahan (hold) dengan apt-mark showhold. Pertukarannya ialah kernel yang ditahan tidak akan menerima sebarang tampalan keselamatan, jadi tentukan bila anda akan menjalankan sudo apt-mark unhold sebelum anda menetapkan status tahan tersebut.