#!/usr/bin/env bash
#
# set-default-kernel.sh
# Rocky Linux 9: Detect BIOS/UEFI -> list installed kernels -> set default kernel
# Requires: grubby (preferred). Falls back to grub2-set-default if grubby is missing.
set -euo pipefail
# --- Helpers ---
die() { echo "ERROR: $*" >&2; exit 1; }
need_root() {
if [[ $EUID -ne 0 ]]; then
echo "[i] Root 권한이 필요합니다. sudo로 재실행합니다..."
exec sudo -E "$0" "$@"
fi
}
# --- Ensure root ---
need_root "$@"
# --- Detect firmware ---
if [[ -d /sys/firmware/efi ]]; then
FW="UEFI"
GRUB_CFG_READ="/etc/grub2-efi.cfg"
GRUB_CFG_WRITE="/boot/efi/EFI/rocky/grub.cfg"
else
FW="BIOS"
GRUB_CFG_READ="/etc/grub2.cfg"
GRUB_CFG_WRITE="/boot/grub2/grub.cfg"
fi
echo "[i] Firmware : $FW"
echo "[i] GRUB cfg : read=$GRUB_CFG_READ, write=$GRUB_CFG_WRITE"
HAVE_GRUBBY=0
if command -v grubby >/dev/null 2>&1; then
HAVE_GRUBBY=1
fi
CURRENT_RUNNING="$(uname -r || true)"
echo
echo "===== Installed kernels ====="
KERNELS=() # e.g. /boot/vmlinuz-5.14.0-...
TITLES=() # GRUB menu titles
if [[ $HAVE_GRUBBY -eq 1 ]]; then
# Collect from grubby (BLS-aware)
mapfile -t KERNELS < <(grubby --info=ALL | awk -F= '/^kernel=/{print $2}')
mapfile -t TITLES < <(grubby --info=ALL | awk -F= '/^title=/{print $2}')
DEFAULT_KERNEL="$(grubby --default-kernel 2>/dev/null || true)"
DEFAULT_TITLE="$(grubby --info="$DEFAULT_KERNEL" 2>/dev/null | awk -F= '/^title=/{print $2}')"
else
echo "[!] grubby가 없습니다. 가능한 경우 설치를 권장합니다: dnf install -y grubby"
# Fallback: parse GRUB menu entries (exclude rescue)
mapfile -t TITLES < <(awk -F"'" '$1=="menuentry " && $2 !~ /rescue/ {print $2}' "$GRUB_CFG_READ" 2>/dev/null || true)
# We won't have /boot/vmlinuz paths reliably; fill placeholders
for _ in "${TITLES[@]}"; do KERNELS+=("N/A-without-grubby"); done
DEFAULT_TITLE="$(/usr/bin/grub2-editenv list 2>/dev/null | awk -F= '$1=="saved_entry"{print $2}')"
DEFAULT_KERNEL=""
fi
if [[ ${#TITLES[@]} -eq 0 ]]; then
die "설치된 커널 목록을 찾지 못했습니다."
fi
for i in "${!TITLES[@]}"; do
idx=$((i+1))
mark=""
if [[ -n "${DEFAULT_TITLE:-}" && "${TITLES[$i]}" == "$DEFAULT_TITLE" ]]; then
mark="*default"
fi
# Try to derive version for nicer display
ver="${KERNELS[$i]##*/vmlinuz-}"
if [[ "$ver" == "${KERNELS[$i]}" || -z "$ver" ]]; then
# attempt from title: "Rocky Linux (5.14.0-...) ..."
ver="$(sed -n 's/.*(\(.*\)).*/\1/p' <<< "${TITLES[$i]}")"
fi
running_mark=""
if [[ -n "$CURRENT_RUNNING" && "$ver" == "$CURRENT_RUNNING" ]]; then
running_mark="(running)"
fi
printf "%2d) %-70s %-28s %s\n" "$idx" "${TITLES[$i]}" "$ver" "$mark $running_mark"
done
echo
read -rp "-> 기본 부팅으로 설정할 번호를 입력하세요: " CHOICE
if ! [[ "$CHOICE" =~ ^[0-9]+$ ]] || (( CHOICE < 1 || CHOICE > ${#TITLES[@]} )); then
die "잘못된 선택입니다."
fi
SEL_INDEX=$((CHOICE-1))
SEL_TITLE="${TITLES[$SEL_INDEX]}"
SEL_KERNEL="${KERNELS[$SEL_INDEX]}"
echo
echo "[i] 선택된 항목:"
echo " Title : $SEL_TITLE"
echo " Kernel: ${SEL_KERNEL}"
# --- Apply change ---
if [[ $HAVE_GRUBBY -eq 1 && -n "$SEL_KERNEL" && "$SEL_KERNEL" != "N/A-without-grubby" ]]; then
echo "[i] grubby로 기본 커널 설정 중..."
grubby --set-default "$SEL_KERNEL"
NEW_DEFAULT="$(grubby --default-kernel || true)"
echo "[i] 기본 커널 -> $NEW_DEFAULT"
else
echo "[i] grubby 미사용 경로: GRUB saved_entry를 타이틀로 설정합니다."
grub2-set-default "$SEL_TITLE"
# 재생성(보수적): 일부 환경에서 필요치 않을 수 있으나 안전을 위해 반영
if [[ -w "$GRUB_CFG_WRITE" ]]; then
echo "[i] grub2-mkconfig 실행 중..."
grub2-mkconfig -o "$GRUB_CFG_WRITE" >/dev/null
else
echo "[!] $GRUB_CFG_WRITE 쓰기가 불가하여 mkconfig를 건너뜁니다."
fi
echo "[i] 현재 saved_entry:"
grub2-editenv list || true
fi
echo
echo "완료되었습니다. 재부팅 후 적용됩니다."
echo "현재 실행 중인 커널: $CURRENT_RUNNING"