Skip to content

Instantly share code, notes, and snippets.

@Yousha
Last active April 22, 2025 15:43
Show Gist options
  • Save Yousha/6ebb8901ee114f399bfcd113c708c0cd to your computer and use it in GitHub Desktop.
Save Yousha/6ebb8901ee114f399bfcd113c708c0cd to your computer and use it in GitHub Desktop.
Shell script to update Linux kernel. (Traditionally)
#!/bin/bash
# Update Linux Kernel
# Version: 2.0.0.2
# Description: Script to download, config, compile, and install Linux kernel manually.
# Requirements: Slackware Linux, x86_64 architecture, root privileges.
# Usage: sudo ./update_linux_kernel.sh [<kernel_version>]
# Enable strict mode: Abort on errors, unset variables, and pipe failures.
set -o nounset # Exit if an unbound variable is used.
set -o errexit # Exit if any command fails.
set -o pipefail # Fail pipelines if any command in the pipeline fails.
# Environment / locale settings.
LANG=C
LC_ALL=C
IFS=$'\n\t' # Set IFS to default for better string handling.
# Constants
readonly KERNEL_BASE_URL="https://cdn.kernel.org/pub/linux/kernel"
readonly DEFAULT_KERNEL_VERSION="6.1.24"
readonly BUILD_THREADS=$(( ($(nproc) + 1) / 2 )) # Use half of available cores + 1.
readonly SOURCE_DIR="/usr/src"
# Log messages with timestamps.
log() {
local message="$*"
echo "$message"
}
# Exit with an error message and cleanup.
error_exit() {
log "ERROR: $1"
exit "${2:-1}" # Default exit code is 1 if not provided.
}
# Check if the user is root.
check_root() {
[[ "$EUID" -eq 0 ]] || error_exit "This script must be run as root." 13
}
# Verify system architecture.
check_architecture() {
[[ "$(uname -m)" == "x86_64" ]] || error_exit "Only x86_64 architecture is supported." 1
}
# Print usage instructions.
usage() {
echo "Usage: sudo $0 [<kernel_version>]"
echo "Note: If no kernel_version is provided, the default (${DEFAULT_KERNEL_VERSION}) is used."
}
# Check available disk space (minimum 3GB).
check_disk_space() {
local required_space_kb=3145728 # 3GB in KB.
local available_space=$(df -k --output=avail "$SOURCE_DIR" | tail -1)
[[ "$available_space" -ge "$required_space_kb" ]] || \
error_exit "Insufficient disk space. Need at least 3GB in ${SOURCE_DIR}." 1
}
# Check script dependencies.
check_dependencies() {
local required=("wget" "gcc" "make" "xz" "tar" "git")
local missing=()
for cmd in "${required[@]}"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
missing+=("$cmd")
fi
done
if [[ ${#missing[@]} -gt 0 ]]; then
error_exit "Missing required tools: ${missing[*]}." 1
fi
}
# Download and verify the kernel source.
download_kernel() {
local kernel_version="$1"
local major_version="v${kernel_version%%.*}.x"
local file_source="linux-${kernel_version}.tar.xz"
local url="${KERNEL_BASE_URL}/${major_version}/${file_source}"
mkdir -p "$SOURCE_DIR"
cd "$SOURCE_DIR"
# Remove old files if they exist.
rm -f "${file_source}"*
log "Downloading Linux kernel ${kernel_version}..."
if ! wget --quiet --show-progress --continue --output-document="${file_source}" "${url}"; then
error_exit "Failed to download kernel source from ${url}."
fi
}
# Extract kernel archive.
extract_kernel() {
local kernel_version="$1"
local file_source="linux-${kernel_version}.tar.xz"
local dir_source="linux-${kernel_version}"
if [[ -d "$dir_source" ]]; then
log "Source directory exists, cleaning..."
rm -rf "$dir_source"
fi
log "Extracting kernel source..."
if ! tar --extract --xz --file="${file_source}"; then
error_exit "Failed to extract kernel source."
fi
log "Removing downloaded kernel archive..."
rm -f "${file_source}"*
}
# Configure kernel build.
configure_kernel() {
local kernel_version="$1"
local dir_source="linux-${kernel_version}"
cd "${SOURCE_DIR}/${dir_source}"
log "Using current system kernel config as base..."
if [[ -f /proc/config.gz ]]; then
zcat /proc/config.gz > .config
elif [[ -f /boot/config-$(uname -r) ]]; then
cp "/boot/config-$(uname -r)" .config
else
error_exit "Could not find current kernel config."
fi
log "Preparing kernel build configs..."
make ARCH=x86_64 olddefconfig || error_exit "Failed to configure kernel."
}
# Compile kernel.
build_kernel() {
local kernel_version="$1"
local dir_source="linux-${kernel_version}"
cd "${SOURCE_DIR}/${dir_source}"
log "Building kernel... (${BUILD_THREADS} threads)"
if ! make ARCH=x86_64 -j"${BUILD_THREADS}" all; then
error_exit "Kernel build failed."
fi
}
# Install kernel related files.
install_kernel() {
local dir_source="linux-${kernel_version}"
cd "${SOURCE_DIR}/${dir_source}"
log "Installing kernel modules... (/lib/modules/)"
if ! make modules_install; then
error_exit "Failed to install kernel modules."
fi
log "Installing kernel headers... (/usr/include/)"
if ! make headers_install INSTALL_HDR_PATH=/usr; then
error_exit "Failed to install kernel headers."
fi
log "Installing kernel and System.map... (/boot/)"
if ! make install; then
error_exit "Failed to install kernel."
fi
}
# Regenerate InitialRAMFilesystem.
regenerate_initramfs() {
local kernel_version="$1"
local script_path="/usr/share/mkinitrd/mkinitrd_command_generator.sh"
[[ -x "$script_path" ]] || error_exit "InitRAMFs script not found or not executable."
log "Regenerating InitRAMFs for kernel ${kernel_version}..."
if ! "$script_path" -k "${kernel_version}" > update_mkinit.sh; then
error_exit "Failed to generate InitRAMFs script."
fi
chmod +x update_mkinit.sh
if ! ./update_mkinit.sh; then
error_exit "Failed to regenerate InitRAMFs."
fi
rm -f update_mkinit.sh
}
main() {
# Use the first argument as kernel version, or default if not provided.
local kernel_version="${1:-$DEFAULT_KERNEL_VERSION}"
log "Starting kernel update to version ${kernel_version}..."
log "System: $(uname -a)"
check_root
check_architecture
check_dependencies
check_disk_space
download_kernel "$kernel_version"
extract_kernel "$kernel_version"
configure_kernel "$kernel_version"
build_kernel "$kernel_version"
install_kernel
regenerate_initramfs "$kernel_version"
cleanup_old_kernels
log "Kernel update to version ${kernel_version} completed successfully."
log "System needs to be rebooted to use the new kernel."
exit 0
}
# Show usage if -h or --help is provided.
if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
usage
exit 0
fi
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment