Created
July 19, 2023 00:08
-
-
Save rversteegen/32bb0b2786ee1092762627f0f7035427 to your computer and use it in GitHub Desktop.
My GRUB linux boot entry generation script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
#exec tail -n +3 $0 | |
# Be careful not to change | |
# the 'exec tail' line above. | |
# This script lives in /etc/grub.d/ | |
# 2015,2022 Ralph Versteegen | |
# The menuentry template was orginally generated by /etc/grub.d/10_linux | |
import os | |
import glob | |
import re | |
import sys | |
import subprocess | |
def tell(*args): | |
print(*args, file = sys.stderr) | |
def run(cmd): | |
tell(cmd) | |
ret = subprocess.check_output(cmd.split()).decode('utf-8').rstrip() | |
tell(" ->", ret) | |
return ret | |
# Don't use initrd; the kernel image has it builtin and this breaks it | |
# I blame the patch applied in the SlackBuild to GRUB2 which makes it look for /boot/initrd.gz... | |
#################### bootflags | |
# Useful kernel params: | |
# rootdelay= [KNL] Delay (in seconds) to pause before attempting to | |
# mount the root filesystem | |
# S [KNL] Run init in single mode | |
# libata.force=1.00:1.5,norst,udma4 or udma3 pio4 etc | |
bootflags = "rootflags=subvol=root rootfstype=btrfs ro" | |
#################### disks | |
# Find HDD and SSD devices which have mounted partitions | |
disks = {} | |
for part in ("/mnt/btrfs_ssd", "/mnt/btrfs_pool", "/mnt/btrfs_hdd"): | |
if not os.path.isdir(part): | |
continue | |
part_dev = run("findmnt -vfn -o SOURCE " + part) | |
if part not in disks: | |
# Trim the partition number, to get disk's device | |
disks[part] = re.match("[^0-9]*", part_dev).group(0) | |
tell("Found disks:", disks) | |
#################### Entry for each disk | |
for disk_path,disk_dev in disks.items(): | |
# PARTUUID of the root's btrfs partition | |
# PARTUUID shown by "lsblk -f -o +PARTUUID,SIZE", and by gdisk 'i' (information) as "Partition unique GUID" | |
# It is stored in MBR or GPT | |
root_partuuid = run("findmnt -vfn -o PARTUUID " + disk_path) | |
# Check fstab for a /mnt/boot entry | |
# It's also possible to search HDD for LABEL=boot using blkid | |
#boot_dev = run("findmnt -vfn -o UUID /mnt/boot") | |
# Check for a partition labelled "boot" | |
try: | |
boot_dev = run("blkid -t LABEL=boot -o device " + " ".join(glob.glob(disk_dev + "*"))) | |
#if boot_dev: | |
tell("Found boot partition " + boot_dev) | |
boot_uuid = run("lsblk -n -o UUID " + boot_dev) | |
#else: | |
except subprocess.CalledProcessError: | |
# No boot partition, using /boot | |
# UUID aka FS UUID is stored in the FS itself | |
boot_uuid = run("findmnt -vfn -o UUID " + disk_path) | |
template = """ | |
menuentry 'Slackware GNU/Linux {NAME}' --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-new' {{ | |
load_video | |
insmod gzio | |
insmod part_msdos | |
insmod part_gpt | |
insmod btrfs | |
insmod ext2 | |
echo 'Searching for boot partition...' | |
search.fs_uuid {BOOTUUID} root | |
echo 'Loading Linux from' $root | |
linux /root/boot/{IMAGE} {BOOTFLAGS} root=PARTUUID={ROOTPARTUUID} | |
}} | |
""" | |
for image_name in ("vmlinuz", "vmlinuz-backup"): | |
image_path = disk_path + "/root/boot/" + image_name | |
if os.path.isfile(image_path): | |
name = os.readlink(image_path) + " on " + disk_path | |
print(template.format(ROOTPARTUUID = root_partuuid, | |
BOOTUUID = boot_uuid, | |
BOOTFLAGS = bootflags, | |
IMAGE = image_name, | |
NAME = name)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment