Gentoo Linux – kernel_update script, a Quick Helper to Update Your Kernel

make menuconfig

Keeping your kernel up to date on Gentoo can be a bit daunting, especially when you are running the “keyworded” kernel, meaning not the stable version, but the “always latest” version by keyword ~amd64. There’s a new version almost every week and updating it manually can be quite annoying over time. At least it felt for me …

make
make modules
make modules_install
make install

Then after that, updating the grub config … And what was the command to update the kernel-dependent modules again? Oh ya …

emerge @module-rebuild

For some reason, I can never remember that one … Don’t ask me why.

So, I came up with a little helper in form of a bash script that does pretty much all the work for me, all I have to do is tell it which kernel version I want to have and it does all the magic for me. All I need to do from time to time is clean up old kernel installations.

#!/usr/bin/env bash

# Update script for sys-kernel/gentoo-sources

selected_kernel=""
kernel_base_directory="/usr/src/"
kernel_directory=""
use_latest_kernel=False

run_eclean_kernel=False
number_of_kernel_to_keep=1


# Check for installed programs
declare -A is_installed=(
    ['eclean-kernel']=False
)


for key in ${!is_installed[@]}
    do
        if command -v ${key} > /dev/null
            then
                is_installed["${key}"]=True
        fi
    done


usage() {
    printf "Usage:\n"
    printf "\t$0 [OPTION]\n"

    printf "\nExample:\n"
    printf "\t$0 --latest\t\t\t\tTo compile the latest kernel\n"
    printf "\t$0 --eclean-kernel=2\t\tTo keep the latest 2 kernels in /boot/ for grub to detect\n"
    printf "\t$0 --kernel=linux-5.17.7-gentoo\tTo compile a specific kernel version. (See available kernel versions below)\n"

    printf "\nOptions:\n"
    printf "\t-k, --kernel\t\tThe kernel version you want to compile, see available kernel versions (Example: -k=linux-5.17.7-gentoo)\n"

    printf "\t-e, --eclean-kernel\tThe number of kernels to keep in /boot/ for grub to detect (Example: -e=2 to keep the latest 2)\n"
    printf "\t\t\t\tThis parameter is only considered if 'eclean-kernel' is installed.\n"

    printf "\t-l, --latest\t\tCompile the latest available kernel\n"

    printf "\nAvailable kernel versions (current active version is marked with an asterisk):\n`eselect kernel list`\n" 1>&2;

    exit 1;
}


for i in "$@"
    do
        case $i in
            -k=* | --kernel=*)
                selected_kernel="${i#*=}"
                shift
                ;;

            -e=* | --eclean-kernel=*)
                program_to_check="eclean-kernel"

                if [ ${is_installed["${program_to_check}"]} == True ]
                    then
                        re='^[0-9]+$'

                        if ! [[ ${i#*=} =~ ${re} ]]
                            then
                                echo "Error: Not a number" >&2; exit 1
                        fi

                        run_eclean_kernel=True
                        number_of_kernel_to_keep=${i#*=}
                    else
                        printf "Program 'eclean-kernel' is NOT installed. Ignoring parameter ...\n"
                        printf "To use this feature, install 'eclean-kernel' via 'emerge eclean-kernel'\n"
                fi
                ;;

            -l | --latest)
                use_latest_kernel=True
                ;;

            -* | --*)
                echo "Unknown option $i"
                exit 1
                ;;

            *)
                usage
                ;;
        esac
    done


# If the latest available kernel should be compiled, make sure -k, --kernel are ignored
if [ ${use_latest_kernel} == True ]
    then
        selected_kernel=$(eselect kernel list | tail -1 | awk '{print $2}' | sed 's/[][]//g')
fi


# If no kernel is selected, show help text
if [ -z "${selected_kernel}" ]
    then
        usage
fi


# Set the new kernel directory
kernel_directory="${kernel_base_directory}${selected_kernel}"


# Compiling new kernel
compile_new_kernel() {
    echo "New Kernel Version: ${selected_kernel}"

    echo "Entering kernel directory: ${kernel_directory}";
    cd ${kernel_directory}

    echo "Copying kernel configuration";
    cp /usr/src/linux/.config .

    echo "Switching symlink to new kernel";
    eselect kernel set ${selected_kernel}

    echo "Applying config via 'make olddefconfig'";
    make olddefconfig

    echo "Building new kernel";
    make -j12

    echo "Building modules";
    make modules

    echo "Installing modules";
    make modules_install

    echo "Installing new kernel";
    make install

    echo "Configuring grub2";
    export GRUB_USE_LINUX_LABEL=true
    cp /boot/grub/grub.cfg /boot/grub/grub.cfg.bak

    if [ ${run_eclean_kernel} == True ]
        then
            echo "Cleaning up old kernel files but keeping the latest ${number_of_kernel_to_keep}";

            eclean-kernel -n ${number_of_kernel_to_keep}
        else
            grub-mkconfig -o /boot/grub/grub.cfg
    fi

    echo "Re-compile kernel dependant modules";
    emerge @module-rebuild

    echo "Kernel update complete. You may restart your computer now."

    if [ ${run_eclean_kernel} == False ]
        then
            echo "Feel free to run 'eclean-kernel -n 2' to cleanup old kernel files but keep the latest 2."
    fi
}


if [ -d ${kernel_directory} ]
    then
        current_kernel_version=$(uname -r)

        if [ ${selected_kernel} == "linux-${current_kernel_version}" ]
            then
                echo "You are currently running this kernel version."
                echo "Exiting!";

                exit;
            else
                compile_new_kernel
        fi
    else
        echo "Error: Directory ${kernel_directory} does not exist."
        echo "Exiting!";

        exit;
fi

Save this as e.g. /usr/bin/kernel-update, make sure it is executable via chmod +x /usr/bin/kernel-update and all you have to do to switch to your desired kernel version is (Example: latest installed kernel):

kernel-update --latest

If you want a specific version, first check which versions are available via eselect kernel list and take the version string for a kernel as the argument. For example to build linux-5.17.7-gentoo:

kernel-update -k=linux-5.17.7-gentoo

If you like this script, let me know. I am always open to improvements, so feel free to suggest them!

Leave a Reply