SSD Nodes Learn 🎉 VPS mulai $5.50/bln
Panduan Matt ConnorOleh Matt Connor

Cara Menentukan Kernel VPS untuk Boot Berikutnya

GRUB_DEFAULT tidak berpengaruh pada cloud image Ubuntu. Baca entri menu yang benar-benar tersedia, temukan input vendor, lalu pin boot berikutnya tanpa memicu konsol pemulihan.

Apa yang menentukan kernel yang digunakan VPS saat boot berikutnya

Kernel yang digunakan VPS saat boot berikutnya ditentukan oleh satu file yang dibuat secara otomatis, /boot/grub/grub.cfg. Anda tidak pernah mengedit file tersebut. Edit file input-nya, lalu buat ulang file tersebut. Pada cloud image Ubuntu, salah satu input berasal dari vendor image. Input ini dapat membuat pemilihan menu tidak berpengaruh. Karena itu, GRUB_DEFAULT=1 yang diikuti update-grub tidak mengubah apa pun pada server sewaan, sedangkan dua langkah yang sama berfungsi pada instalasi laptop.

Lakukan dalam urutan berikut. Pastikan kernel tersebut memang dapat Anda pilih. Baca setiap file input, termasuk file yang ditambahkan vendor. Baca output yang dibuat secara otomatis, lalu hitung entri yang benar-benar ada di dalamnya. Setelah itu, pilih metode pinning. Jika salah melakukan langkah ini pada mesin yang hanya dapat Anda akses melalui SSH, Anda mungkin memerlukan konsol pemulihan. Karena itu, jawaban paling aman terdapat di bagian akhir halaman ini dan sering kali merupakan pilihan yang tepat.

Pertama, pastikan kernel tersebut memang dapat Anda tetapkan

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

systemd-detect-virt yang menampilkan kvm, qemu, atau xen berarti Anda menjalankan kernel sendiri, sehingga semua langkah di bawah ini berlaku. Jika yang ditampilkan adalah lxc atau openvz, berarti server Anda menggunakan kernel milik host. Dengan demikian, Anda tidak memiliki bootloader sendiri dan tidak ada yang dapat ditetapkan. Dalam kondisi tersebut, uname -r melaporkan versi yang sama sekali tidak muncul di /boot/vmlinuz-* karena kernel yang sedang berjalan adalah milik host. Tidak ada pengaturan pada disk Anda yang dapat mengubahnya.

ls -1 /boot/vmlinuz-* adalah daftar kernel sebenarnya yang dapat Anda pilih. Jika hanya berisi satu baris, kernel sebelumnya sudah dihapus dan tidak ada pengaturan bootloader yang dapat mengembalikannya. Hal ini biasanya terjadi saat autoremove. Anda perlu memahami proses tersebut sebelum membersihkan kernel lama di Ubuntu pada server yang penting bagi Anda.

File yang Anda edit bukan file yang dibaca GRUB

/etc/default/grub berisi assignment variabel shell biasa. File ini merupakan input. /boot/grub/grub.cfg adalah output, yang diawali dengan # DO NOT EDIT THIS FILE beserta alasannya. Apa pun yang Anda tulis ke file output akan hilang saat paket kernel diinstal atau dihapus, karena skrip paket tersebut membuat ulang file itu.

cat /usr/sbin/update-grub

update-grub adalah wrapper. Perintah ini menjalankan grub-mkconfig -o /boot/grub/grub.cfg, yang membaca variabel, menjalankan setiap skrip di /etc/grub.d/, lalu menulis hasilnya. Dua perintah, satu arah: input masuk, lalu grub.cfg dihasilkan.

Yang mengesampingkan pengaturan Anda: /etc/default/grub.d

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

Path kedua adalah bagian yang sering terlewat. grub-mkconfig membaca /etc/default/grub terlebih dahulu, lalu setiap file *.cfg di /etc/default/grub.d/ sesuai urutan glob. Baca kode yang melakukannya:

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

Sourcing menggunakan shell biasa, sehingga assignment terakhir yang berlaku. Ubuntu cloud images menyertakan file di direktori tersebut, dan file-file itu menetapkan hal seperti timeout serta command line kernel setelah file Anda selesai dibaca. GRUB_TIMEOUT=10 Anda di /etc/default/grub ditimpa beberapa saat kemudian oleh file vendor yang menetapkannya ke 0. Perintah grep di atas menampilkan assignment yang tepat pada image Anda, jadi gunakan hasil tersebut, bukan mengandalkan kalimat ini.

Aturan praktisnya: simpan pengaturan Anda sendiri dalam file yang terurut paling akhir, seperti /etc/default/grub.d/99-local.cfg, bukan dengan mengedit /etc/default/grub. Dengan demikian, tidak ada file yang disertakan oleh image yang dapat diproses setelah file Anda.

Mengapa GRUB_FORCE_PARTUUID membuat pemilihan menu menjadi 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.cfg

GRUB_FORCE_PARTUUID menginstruksikan generator untuk menemukan root filesystem berdasarkan UUID partisi. Nilai ini ditulis langsung ke command line kernel sebagai root=PARTUUID=..., bukan mencari UUID filesystem saat boot. Vendor image menetapkan nilai ini agar satu disk image dapat melakukan boot secara andal pada hardware yang bukan tempat image tersebut dibuat. Perintah grep kedua menampilkan kode yang memproses variabel tersebut, yaitu di /etc/grub.d/10_linux. Script itu berada pada disk Anda sendiri dan menjadi acuan utama untuk mengetahui perilaku image Anda.

Konsekuensi inilah yang penting. Pada jalur tersebut, generator menulis boot entry langsung, bukan daftar lengkap kernel yang terpasang. Hitung hasil akhirnya.

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

Jika hasilnya 1, tidak ada entry kedua yang dapat dipilih. Jadi, GRUB_DEFAULT=1 merujuk ke entry yang tidak ada. GRUB tidak dapat menyelesaikan rujukan tersebut, sehingga melakukan boot dari entry pertama, yaitu kernel baru yang ingin Anda hindari. grub-set-default juga tidak membantu karena bagian yang bermasalah bukan nilai default. Menu yang ingin Anda pilih memang tidak pernah dibuat.

Untuk mengembalikan menu lengkap, pindahkan file vendor tersebut ke lokasi lain dan pratinjau hasilnya sebelum menerapkannya. grub-mkconfig tanpa -o menulis ke standard output dan tidak mengubah apa pun pada disk.

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 berubah dari 1 menjadi beberapa berarti entry muncul setelah pemaksaan tersebut dihapus. Belum ada perubahan yang ditulis. Kembalikan file tersebut jika hasil hitungan kedua tidak sesuai, karena PARTUUID yang dipaksakan itulah yang digunakan image dari provider Anda untuk menemukan root filesystem. Menghapusnya membuat mesin menggunakan jalur pencarian sebagai gantinya. Buat snapshot sebelum menjalankan update-grub secara nyata.

Jika tujuan Anda hanya agar sistem tetap berjalan setelah satu kernel bermasalah, berhenti di sini dan gunakan opsi yang lebih aman di bagian berikutnya. Membangun ulang boot menu pada server remote untuk mengatasi satu upgrade berisiko lebih besar daripada masalahnya.

Mengapa nomor entri bukan pilihan yang tepat untuk dipatok

GRUB_DEFAULT menerima nomor, judul, atau identifier. Nomor menghitung entri tingkat teratas mulai dari 0. Entri bertingkat menggunakan > sebagai pemisah, sehingga GRUB_DEFAULT="1>2" berarti entri pada indeks 2 di dalam submenu pada indeks 1.

Indeks dapat berubah. 10_linux mencantumkan kernel dari yang terbaru terlebih dahulu, sehingga pemasangan kernel baru menggeser setiap entri lama ke bawah satu posisi, sedangkan penghapusan kernel menggesernya ke atas. 1>2 yang telah Anda buat dengan cermat tetap berhasil diproses setelah perubahan itu. Namun, kini perintah tersebut merujuk ke kernel yang berbeda. Tidak ada error atau peringatan. Anda baru mengetahuinya setelah reboot.

Identifier tidak berubah karena masing-masing memuat versi kernel. Tampilkan identifier Anda:

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

Abaikan beberapa baris pertama output. Baris tersebut berisi variabel yang ditetapkan pada header. Setelah itu, sisi kiri adalah judul yang dilihat pembaca, sedangkan sisi kanan adalah identifier yang Anda teruskan ke berbagai tool. Untuk entri di dalam submenu, gabungkan identifier submenu dan identifier entri dengan >, dalam urutan tersebut, sama persis seperti pada bentuk numeriknya.

Boot kernel sebelumnya sekali dengan grub-reboot

Pemilihan satu kali adalah langkah yang tepat pada server jarak jauh karena pilihan tersebut akan membatalkan dirinya sendiri. grub-reboot menulis next_entry ke dalam /boot/grub/grubenv. GRUB membaca variabel tersebut, menghapusnya, lalu menyimpan nilai yang sudah dihapus sebelum melakukan boot apa pun. Dengan demikian, kernel yang mengalami panic tidak akan dicoba lagi pada boot berikutnya. Anda mendapatkan satu kesempatan, lalu mesin kembali ke default normalnya secara otomatis.

Pertama, pastikan konfigurasi yang dihasilkan memang membaca variabel tersebut:

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

Anda harus melihat baris load_env dan blok yang menetapkan default dari next_entry. Jika grep tidak menghasilkan apa pun, image Anda tidak pernah membaca grubenv saat boot. Akibatnya, grub-reboot akan diterima di shell, lalu diabaikan oleh bootloader. Ini adalah jalur boot langsung yang dipaksakan dari bagian sebelumnya, tetapi muncul di tempat kedua.

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

grub-editenv list sekarang seharusnya menampilkan baris next_entry= yang berisi tepat nilai yang Anda berikan. Buka console provider Anda di tab browser, lalu lakukan reboot dan periksa hasilnya.

sudo reboot
uname -r

Jika uname -r melaporkan versi yang lebih lama, berarti pin berhasil. Jika yang dilaporkan adalah versi baru, berarti identifier tidak dapat di-resolve atau grubenv tidak sedang dibaca. Apa pun hasilnya, mesin tetap aktif. Inilah tujuan penggunaan bentuk satu kali.

Buat pilihan tetap dengan GRUB_DEFAULT=saved

GRUB_DEFAULT=saved membuat nilai default berasal dari saved_entry dalam grubenv. Anda menetapkan nilai tersebut dengan grub-set-default. Nilai ini tetap bertahan setelah instalasi kernel karena update-grub menulis ulang grub.cfg dan tidak pernah mengubah 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

Perintah terakhir harus mencetak set default="${saved_entry}". Jika mencetak set default="0", berarti sesuatu yang dimuat setelah file Anda mengatur GRUB_DEFAULT kembali ke nilai literal. Karena itu, tampilkan kembali /etc/default/grub.d/ dan periksa bahwa 99-local.cfg benar-benar berada di urutan terakhir.

GRUB_SAVEDEFAULT=true adalah pengaturan yang berbeda dan mudah tertukar dengan pengaturan ini. Pengaturan tersebut menyimpan kernel yang baru saja Anda boot sebagai default baru. Dengan demikian, default mengikuti boot terakhir yang berhasil. Pada server, reboot tanpa pengawasan dapat mengubah pilihan yang Anda tetapkan secara diam-diam. Biarkan pengaturan ini nonaktif, kecuali memang itu yang Anda inginkan.

Pemilihan berdasarkan identifier tetap dapat gagal dalam satu kondisi. Jika kernel yang dirujuk dihapus, identifier tersebut tidak lagi dapat ditemukan dan sistem kembali menggunakan entri pertama. Karena itu, tahan paket tersebut atau cegah kernel itu dari autoremove.

Menampilkan menu pada konsol provider

Pemilihan secara interaktif memerlukan menu yang tampil di layar, tetapi image cloud menyembunyikannya. Tambahkan pengaturan berikut ke file yang diproses terakhir, lalu jalankan sudo update-grub.

GRUB_TIMEOUT=10
GRUB_TIMEOUT_STYLE=menu
GRUB_RECORDFAIL_TIMEOUT=10

GRUB_TIMEOUT_STYLE=hidden bersama GRUB_TIMEOUT=0 menyembunyikan menu sepenuhnya. Akibatnya, orang yang memantau konsol akan langsung melihat pesan kernel dan menyimpulkan bahwa bootloader dilewati. GRUB_RECORDFAIL_TIMEOUT adalah timeout terpisah yang digunakan setelah boot tidak selesai. Image cloud juga menetapkannya ke 0. Karena itu, server yang baru saja gagal melakukan boot tetap tidak berhenti untuk menunggu input Anda.

Jika provider Anda menyediakan konsol serial, bukan konsol grafis, dan Anda tetap tidak melihat apa pun, GRUB menulis ke terminal yang tidak dapat Anda lihat. Tambahkan kedua baris berikut secara bersamaan. Baris pertama memilih output, sedangkan baris kedua mengonfigurasi port:

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

Mulai sekarang, setiap proses boot akan mendapat tambahan waktu sepuluh detik. Kembalikan timeout ke 0 setelah selesai.

Opsi yang lebih aman daripada mengedit bootloader

Mengubah input bootloader pada mesin yang hanya Anda akses melalui SSH merupakan opsi dengan risiko tertinggi di halaman ini. Ada cara yang lebih sederhana, dan biasanya cara tersebut menyelesaikan masalah yang sebenarnya.

Tahan paket kernel. Jika tujuannya adalah "jangan berikan kernel yang lebih baru", sampaikan hal itu kepada package manager, bukan 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 showhold

Gunakan nama apa pun yang dicetak oleh perintah pertama, karena cloud image biasanya memasang varian virtual atau kvm, bukan generic. Paket yang ditahan akan dilewati oleh apt upgrade, yang menandainya dengan The following packages have been kept back:, dan juga dilewati oleh unattended upgrades di Ubuntu. Konsekuensinya nyata: kernel yang ditahan tidak lagi menerima security fix. Karena itu, anggap penahanan ini sebagai jeda yang memiliki tanggal berakhir, lalu lepaskan dengan sudo apt-mark unhold. Jika Anda menghindari update kernel karena reboot menyebabkan downtime, bukan karena kernel tertentu bermasalah, live kernel patching pada VPS adalah solusi yang sesuai.

Buat snapshot sebelum upgrade. Snapshot dapat dipulihkan dalam hitungan menit, tanpa mengetik melalui console dan tanpa risiko perubahan bootloader yang hanya diterapkan sebagian. Buat snapshot, lakukan upgrade, reboot, lalu verifikasi. Jika kernel baru bermasalah, lakukan rollback sehingga jalur boot kembali persis seperti sebelumnya.

Gunakan console atau rescue image untuk mesin yang sudah tidak aktif. Setelah server tidak dapat boot, konfigurasi bootloader bukan tempat untuk memperbaikinya. Jalur pemulihan tersebut merupakan prosedur tersendiri: langkah yang harus dilakukan ketika VPS tidak dapat boot setelah update kernel.

Hal yang rusak dan pesan yang akan Anda lihat

Perubahan Anda pada /boot/grub/grub.cfg hilang. Paket kernel diinstal atau dihapus, skrip pemeliharanya menjalankan update-grub, lalu file dibuat ulang dari input tersebut. Header # DO NOT EDIT THIS FILE mencantumkan dua lokasi input. Edit lokasi tersebut.

grub-editenv: error: environment block too small. /boot/grub/grubenv hilang atau terpotong. Buat ulang dengan sudo grub-editenv /boot/grub/grubenv create, lalu tetapkan kembali nilai Anda dan konfirmasikan dengan sudo grub-editenv list.

Kernel yang dipatok mengalami panic dengan VFS: Unable to mount root fs on unknown-block(0,0). Entri yang Anda patok menunjuk ke kernel atau initrd yang sudah tidak ada di disk. Hal ini biasanya terjadi karena paket dihapus, sementara pengenalnya masih tercantum dalam grubenv. Pulihkan sistem dengan mem-boot entri yang berfungsi dari konsol, lalu hapus nilai yang sudah tidak berlaku.

uname -r tidak berubah setelah reboot yang seharusnya mengubahnya. Periksa tiga hal berikut secara berurutan: apakah grub-editenv list masih menampilkan nilai Anda atau sudah digunakan; apakah pengenal yang Anda tetapkan muncul dalam grub.cfg saat ini; apakah grub.cfg berisi baris set default yang membaca variabel yang Anda tetapkan. Salah satu dari tiga hal tersebut selalu menjelaskannya.

Menu muncul sendiri setelah crash. GRUB mencatat boot yang gagal dalam grubenv sebagai recordfail=1. Hal ini memaksa menu tampil pada boot berikutnya agar administrator dapat melakukan intervensi. Hapus dengan sudo grub-editenv /boot/grub/grubenv unset recordfail setelah mesin kembali sehat.


Satu kalimat yang perlu diingat: file yang Anda edit bukan file yang dibaca GRUB, dan pada image cloud, celah di antara keduanya merupakan sumber kebingungan. Baca konfigurasi yang dibuat terlebih dahulu. Semua keputusan di halaman ini didasarkan pada isinya yang sebenarnya.

FAQ

Mengapa GRUB_DEFAULT=1 tidak mengubah kernel yang digunakan VPS saat boot?

Karena pada cloud image Ubuntu, /boot/grub/grub.cfg yang dihasilkan sering hanya memiliki satu entri boot. Oleh karena itu, indeks 1 tidak merujuk ke apa pun dan GRUB kembali menggunakan entri pertama. Konfirmasikan dengan sudo grep -cE '^\s*(menuentry|submenu) ' /boot/grub/grub.cfg. Jika hasilnya 1, itulah penyebabnya. Penyebabnya adalah GRUB_FORCE_PARTUUID, yang ditetapkan oleh vendor image dalam file di bawah /etc/default/grub.d/. Pengaturan ini membuat generator menggunakan jalur boot langsung, bukan membuat daftar lengkap kernel yang terpasang. Temukan file tersebut dengan grep -rn GRUB_FORCE_PARTUUID /etc/default/grub /etc/default/grub.d/.

Bagaimana cara mem-boot kernel sebelumnya satu kali saja?

Jalankan sudo grub-reboot '<identifier>' dengan identifier yang disalin dari grub.cfg milik Anda, lalu reboot setelah konsol provider terbuka. GRUB menghapus next_entry sebelum melakukan boot. Dengan demikian, pilihan tersebut hanya berlaku untuk satu kali percobaan, dan kernel yang mengalami panic tidak akan dicoba lagi. Konfirmasikan bahwa nilainya telah diterapkan dengan sudo grub-editenv list. Sebelum mengandalkannya, jalankan sudo grep -n next_entry /boot/grub/grub.cfg, karena image yang konfigurasinya tidak pernah memuat grubenv akan mengabaikan perintah tersebut tanpa menampilkan error.

Sebaiknya menggunakan nomor entri atau identifier?

Gunakan identifier. Nomor entri adalah posisi dalam daftar yang 10_linux susun ulang dengan urutan terbaru di depan. Karena itu, pemasangan atau penghapusan kernel apa pun dapat menggeser nomor tersebut. 1>2 yang sudah tidak sesuai masih dapat merujuk ke entri yang benar-benar ada tetapi salah, tanpa peringatan apa pun. Identifier berisi versi kernel. Jadi, identifier akan cocok dengan kernel yang dimaksud atau gagal ditemukan. Tampilkan identifier dengan sudo grep -n menuentry_id_option /boot/grub/grub.cfg, lalu salin string dalam tanda kutip yang mengikuti setiap baris entri.

Apakah menahan paket kernel lebih aman daripada mengubah bootloader?

Untuk tujuan umum, ya. sudo apt-mark hold linux-image-virtual linux-headers-virtual mencegah kernel yang lebih baru dipasang. Dengan demikian, jalur boot tidak berubah dan tidak ada konfigurasi yang dapat salah akibat penggunaan konsol yang mungkin tidak dapat Anda akses. Periksa terlebih dahulu nama flavour yang terpasang pada server Anda dengan apt list --installed, lalu verifikasi penahanan paket tersebut dengan apt-mark showhold. Konsekuensinya, kernel yang ditahan tidak menerima perbaikan keamanan. Karena itu, tentukan kapan Anda akan menjalankan sudo apt-mark unhold sebelum menerapkan penahanan paket.