16.09.2016

Linux kernel patch update skript

Ich bin ein großer Freund von "Selber machen" - zumindest am Computer. In der echten Welt hab ich eher so zwei linke Hände ;)

Das resultiert darin, dass mein Server zuhause mit einem selbst gelöteten Linux arbeitet, nämlich mit "Linux from Scratch", bei dem man alle Pakete selbst als Quelltext herunterlädt und installiert.

Zuerst hatte ich mal SuSE verwendet, aber die Paketverwaltung und die Abhängigkeiten waren mir dann zu viel geworden. Also dann: alles selbst kompilieren und genau sehen, welche Abhängigkeiten unbedingt nötig sind und welche nicht. Bei vorgefertigten Linux-Distributionen wird eigentlich immer das maximale Kunstwerk installiert, und genau das wollte ich nicht.

Diese DIY-Methode hat auch den Vorteil, dass man immer genau die gewünschte Version von Software hat, z.B. beim Kernel auch immer die neueste, die dann z.B. aktuelle Hardware unterstützt.

Ich will hier ein kleines Skript vorstellen, das ich mir vor längerer Zeit als Hilfsmittel gebastelt habe, um den Linux-Kernel immer auf dem aktuellen Stand zu halten.

Das Skript lädt eine neue Version in Form der Differenzdatei herunter, wendet dann diesen einen oder auch mehrere Patches an und speichert das Ergebnis wieder als neuestes Kernelpaket. Das kann man dann auch gleich kompilieren und dem Bootload unterjubeln (dazu hab ich ein separates Skript).

In blau hab ich ein paar Bemerkungen dazugeschrieben; das Skript ist aber eigentlich selbsterklärend - finde ich ;)

#!/bin/sh -e

msg() { echo "$*" 1>&2; }
err() { msg "$*"; exit 1; }


# dies ist die Basisversion des Kernels
base="${1:-4.7}"
# "von" Version
old="${2:-0}"

# "nach" Version
new="${3:-4}"
v="${base}.${old}"
latest="linux-${base}.${new}"

# die Files heißen 4.7 und nicht 4.7.0
test "${old}" = "0" && v="${base}"
test "${new}" = "0" && latest="linux-${base}"



url="https://cdn.kernel.org/pub/linux/kernel/v4.x"
wget="wget -q --no-check-certificate"

kl="linux-${base}.${new}"
ext="xz"
source="/sources"

# nix mehr zu tun, schon da
test -f "${kl}" && err "# Kernel ${kl} exists"

msg "unpack linux-${v}"
work=$(mktemp -d -p "${source}")
cd "${work}"
tar xf "${source}/linux-${v}.tar.${ext}"
mv "linux-${v}" "${latest}"

# wenn der alte Kernel 0 ist, reicht der neueste Patch allein
if [ "${old}" = "0" ]
then
    patch="patch-${base}.${new}.${ext}"
    test -f "${patch}" || ${wget} "${url}/${patch}"
    test -f "${patch}" || err "! download ${patch} failed"
    msg "apply ${patch}"
    xz -cd "${patch}" | patch -d "${latest}" -Nstp1
else

# ansonsten jeden patch von x nach x+1 holen
    while [ "${old}" -lt "${new}" ]
    do
        next=$(expr "${old}" + 1)
        ipatch="patch-${base}.${old}-${next}.${ext}"
        test -f "${ipatch}" || ${wget} "${url}/incr/${ipatch}"
        test -f "${ipatch}" || err "! download ${ipatch} failed"
        msg "apply ${ipatch}"
        xz -cd "${ipatch}" | patch -d "${latest}" -Nstp1
        rm -f "${ipatch}"
        old="${next}"
    done
fi
rc="${?}"

if [ ${rc} -eq 0 ]
then
    msg "pack ${latest}"
    egrep "^(VERSION|PATCHLEVEL|SUBLEVEL) = " "${latest}"/Makefile 2>/dev/null
    tar cf - "${latest}" | xz -9 > ../"${latest}.tar.${ext}"
    msg "cleanup tmp"
    cd ..
    rm -fr "${work}"
else
    err "! patch failed, rc=${rc}"
fi