diff options
Diffstat (limited to '')
-rwxr-xr-x | update-initramfs | 398 | ||||
-rw-r--r-- | update-initramfs.8 | 95 | ||||
-rw-r--r-- | update-initramfs.conf.5 | 35 |
3 files changed, 528 insertions, 0 deletions
diff --git a/update-initramfs b/update-initramfs new file mode 100755 index 0000000..4bb8d8a --- /dev/null +++ b/update-initramfs @@ -0,0 +1,398 @@ +#!/bin/sh + +BOOTDIR=/boot +CONF=/etc/initramfs-tools/update-initramfs.conf +mode="" +version="" +update_initramfs=yes +backup_initramfs=no + +set -e + +[ -r ${CONF} ] && . ${CONF} + +if [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ] && [ $# = 1 ] && [ "$1" = -u ]; then + if dpkg-trigger --no-await update-initramfs; then + echo "update-initramfs: deferring update (trigger activated)" + exit 0 + fi +fi + +usage() +{ + cat << EOF + +Usage: update-initramfs {-c|-d|-u} [-k version] [-v] [-b directory] + +Options: + -k version Specify kernel version or 'all' + -c Create a new initramfs + -u Update an existing initramfs + -d Remove an existing initramfs + -b directory Set alternate boot directory + -v Be verbose + +See update-initramfs(8) for further details. + +EOF +} + +usage_error() +{ + if [ -n "${1:-}" ]; then + printf "%s\\n\\n" "${*}" >&2 + fi + usage >&2 + exit 2 +} + +mild_panic() +{ + if [ -n "${1:-}" ]; then + printf "%s\\n" "${*}" >&2 + fi + exit 0 +} + +panic() +{ + if [ -n "${1:-}" ]; then + printf "%s\\n" "${*}" >&2 + fi + exit 1 +} + +verbose() +{ + if [ "${verbose}" = 1 ]; then + printf "%s\\n" "${*}" + fi +} + +set_initramfs() +{ + initramfs="${BOOTDIR}/initrd.img-${version}" +} + + +# backup initramfs while running +backup_initramfs() +{ + [ ! -r "${initramfs}" ] && return 0 + initramfs_bak="${initramfs}.dpkg-bak" + [ -r "${initramfs_bak}" ] && rm -f "${initramfs_bak}" + ln -f "${initramfs}" "${initramfs_bak}" 2>/dev/null \ + || cp -a "${initramfs}" "${initramfs_bak}" + verbose "Keeping ${initramfs_bak}" +} + +# keep booted initramfs +backup_booted_initramfs() +{ + initramfs_bak="${initramfs}.dpkg-bak" + + # first time run thus no backup + [ ! -r "${initramfs_bak}" ] && return 0 + + # chroot with no /proc + [ ! -r /proc/uptime ] && rm -f "${initramfs_bak}" && return 0 + + # no kept backup wanted + [ "${backup_initramfs}" = "no" ] && rm -f "${initramfs_bak}" && return 0 + + # no backup yet + if [ ! -r "${initramfs}.bak" ]; then + mv -f "${initramfs_bak}" "${initramfs}.bak" + verbose "Backup ${initramfs}.bak" + return 0 + fi + + # keep booted initramfs + boot_initramfs= + uptime_days=$(awk '{printf "%d", $1 / 3600 / 24}' /proc/uptime) + if [ -n "$uptime_days" ]; then + boot_initramfs=$(find "${initramfs}.bak" -mtime "+${uptime_days}") + fi + if [ -n "${boot_initramfs}" ]; then + mv -f "${initramfs_bak}" "${initramfs}.bak" + verbose "Backup ${initramfs}.bak" + return 0 + fi + verbose "Removing current backup ${initramfs_bak}" + rm -f "${initramfs_bak}" +} + +# nuke generated copy +remove_initramfs_bak() +{ + [ -z "${initramfs_bak:-}" ] && return 0 + rm -f "${initramfs_bak}" + verbose "Removing ${initramfs_bak}" +} + + +generate_initramfs() +{ + echo "update-initramfs: Generating ${initramfs}" + OPTS="-o" + if [ "${verbose}" = 1 ]; then + OPTS="-v ${OPTS}" + fi + # shellcheck disable=SC2086 + if mkinitramfs ${OPTS} "${initramfs}.new" "${version}"; then + mv -f "${initramfs}.new" "${initramfs}" + # Guard against an unclean shutdown + sync -f "${initramfs}" + else + mkinitramfs_return="$?" + remove_initramfs_bak + rm -f "${initramfs}.new" + echo "update-initramfs: failed for ${initramfs} with $mkinitramfs_return." >&2 + exit $mkinitramfs_return + fi +} + +# Invoke bootloader +run_bootloader() +{ + # invoke policy conformant bootloader hooks + if [ -d /etc/initramfs/post-update.d/ ]; then + run-parts --arg="${version}" --arg="${initramfs}" \ + /etc/initramfs/post-update.d/ + return 0 + fi +} + +# ro /boot is not modified +ro_boot_check() +{ + # check irrelevant inside of a chroot + if [ ! -r /proc/mounts ] || ischroot; then + return 0 + fi + + # shellcheck disable=SC1004 + boot_opts=$(awk '/boot/{if ((match($4, /^ro/) || match($4, /,ro/)) \ + && $2 == "/boot") print "ro"}' /proc/mounts) + if [ -n "${boot_opts}" ]; then + echo "W: /boot is ro mounted." >&2 + echo "W: update-initramfs: Not updating ${initramfs}" >&2 + exit 0 + fi +} + +get_sorted_versions() +{ + version_list="$( + linux-version list | + while read -r version; do + test -e "${BOOTDIR}/initrd.img-$version" && echo "$version" + done | + linux-version sort --reverse + )" + verbose "Available versions: ${version_list}" +} + +set_current_version() +{ + if [ -f "/boot/initrd.img-$(uname -r)" ]; then + version=$(uname -r) + fi +} + +set_linked_version() +{ + linktarget= + if [ -e /initrd.img ] && [ -L /initrd.img ]; then + linktarget="$(basename "$(readlink /initrd.img)")" + fi + + if [ -e /boot/initrd.img ] && [ -L /boot/initrd.img ]; then + linktarget="$(basename "$(readlink /boot/initrd.img)")" + fi + + if [ -z "${linktarget}" ]; then + return + fi + + version="${linktarget##initrd.img-}" +} + +set_highest_version() +{ + get_sorted_versions + if [ -z "${version_list}" ]; then + version= + return + fi + # shellcheck disable=SC2086 + set -- ${version_list} + version=${1} +} + +create() +{ + if [ -z "${version}" ]; then + usage_error "Create mode requires a version argument" + fi + + set_initramfs + + generate_initramfs + + run_bootloader +} + +update() +{ + if [ "${update_initramfs}" = "no" ]; then + echo "update-initramfs: Not updating initramfs." + exit 0 + fi + + if [ -z "${version}" ]; then + set_highest_version + fi + + if [ -z "${version}" ]; then + set_linked_version + fi + + if [ -z "${version}" ]; then + set_current_version + fi + + if [ -z "${version}" ]; then + verbose "Nothing to do, exiting." + exit 0 + fi + + set_initramfs + + ro_boot_check + + backup_initramfs + + generate_initramfs + + run_bootloader + + backup_booted_initramfs +} + +delete() +{ + if [ -z "${version}" ]; then + usage_error "Delete mode requires a version argument" + fi + + set_initramfs + + echo "update-initramfs: Deleting ${initramfs}" + + rm -f "${initramfs}" "${initramfs}.bak" +} + +# Defaults +verbose=0 + +## + +OPTIONS=$(getopt -o "k:cudvtb:h?" --long help -n "$0" -- "$@") || usage_error + +eval set -- "$OPTIONS" + +while true; do + case "$1" in + -k) + version="$2" + shift 2 + ;; + -c) + mode="c" + shift + ;; + -d) + mode="d" + shift + ;; + -u) + mode="u" + shift + ;; + -v) + verbose="1" + shift + ;; + -t) + # accepted for compatibility, but ignored + shift + ;; + -b) + BOOTDIR="$2" + if [ ! -d "${BOOTDIR}" ]; then + echo "E: ${BOOTDIR} is not a directory." >&2 + exit 1 + fi + shift 2 + ;; + -h|-\?|--help) + usage + exit 0 + ;; + --) + shift + break + ;; + esac +done + +if [ $# -ne 0 ]; then + printf "Extra argument '%s'\\n\\n" "$1" >&2 + usage_error +fi + +# Validate arguments +if [ -z "${mode}" ]; then + usage_error "You must specify at least one of -c, -u, or -d." +fi + +if [ "${version}" = "all" ] \ + || { [ "${update_initramfs}" = "all" ] && [ -z "${version}" ]; }; then + case "${mode}" in + c) + version_list="$(linux-version list)" + ;; + d | u) + get_sorted_versions + ;; + esac + if [ -z "${version_list}" ]; then + verbose "Nothing to do, exiting." + exit 0 + fi + + OPTS="-b ${BOOTDIR}" + if [ "${verbose}" = "1" ]; then + OPTS="${OPTS} -v" + fi + for u_version in ${version_list}; do + verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}" + # shellcheck disable=SC2086 + "${0}" -${mode} -k "${u_version}" ${OPTS} + done + exit 0 +fi + + +case "${mode}" in + c) + create + ;; + d) + delete + ;; + u) + update + ;; +esac diff --git a/update-initramfs.8 b/update-initramfs.8 new file mode 100644 index 0000000..b36fc57 --- /dev/null +++ b/update-initramfs.8 @@ -0,0 +1,95 @@ +.TH UPDATE-INITRAMFS 8 "2014/10/16" "initramfs\-tools" "System Administration" + +.SH NAME +update\-initramfs \- generate an initramfs image + +.SH SYNOPSIS +.B update\-initramfs +.RB { \-c | \-d | \-u } +.RB [ \-k +.IR version ] +.RB [ \-v ] +.RB [ \-b +.IR directory ] +.br +.BR update\-initramfs " " \-h +.SH DESCRIPTION +The +.B update\-initramfs +script manages your initramfs images on your local box. +It keeps track of the existing initramfs archives in /boot. +There are three modes of operation create, update or delete. +You must at least specify one of those modes. + +The initramfs is a gzipped cpio archive. +At boot time, the kernel unpacks that archive into RAM disk, mounts and +uses it as initial root file system. All finding of the root device +happens in this early userspace. + +.SH OPTIONS +.TP +\fB\-k \fI version +Set the specific kernel version for whom the initramfs will be generated. +For example the output of uname \-r for your currently running kernel. +This argument is optional for update. The default is the latest kernel version. + +The use of "all" for the +.I version +string specifies that +.B update\-initramfs +should operate on all installed kernel versions (with \fB\-c\fR), or +on all installed kernel versions that already have an initramfs +(with \fB\-d\fR or \fB\-u\fR). + +.TP +\fB\-c +This mode creates a new initramfs. + +.TP +\fB\-u +This mode updates an existing initramfs. + +.TP +\fB\-d +This mode deletes an existing initramfs. + +.TP +\fB\-v +This option increases the amount of information you are given during +the chosen action. + +.TP +\fB\-b \fI directory +Set an different bootdir for the image creation. + +.TP +\fB\-h\fR, \fB--help\fR +Print a short help page describing the available options in +.B update\-initramfs. + +.SH EXAMPLES + +Update the initramfs of the newest kernel: + +.PP +.B update\-initramfs -u + + +Create the initramfs for a specific kernel: + +.PP +.B update\-initramfs -c -k 2.6.18-1-686 + +.SH FILES +/etc/initramfs-tools/update-initramfs.conf + +.SH AUTHOR +The initramfs-tools are written by Maximilian Attems <maks@debian.org>, +Jeff Bailey <jbailey@raspberryginger.com> and numerous others. + +.SH SEE ALSO +.BR +.IR initramfs.conf (5), +.IR initramfs-tools (7), +.IR mkinitramfs (8), +.IR lsinitramfs (8). diff --git a/update-initramfs.conf.5 b/update-initramfs.conf.5 new file mode 100644 index 0000000..cd1f4ea --- /dev/null +++ b/update-initramfs.conf.5 @@ -0,0 +1,35 @@ +.TH UPDATE-INITRAMFS.CONF 5 "2010/04/05" "initramfs\-tools" "File Formats Manual" + +.SH NAME +update-initramfs.conf \- configuration file for update-initramfs + +.SH DESCRIPTION +The configuration file allows one to disable the update action from +.B update-initramfs. + +.SH GENERAL VARIABLES +.TP +\fB update_initramfs +Default is \fIyes\fP for running the latest initramfs-tools hooks in the +newest Linux image. +Setting it to \fIall\fP updates any known initramfs. +It is possible to set it to \fIno\fP for remote servers or boxes where +conservative manners needs to be applied. This disables +the \fBupdate_initramfs \-u\fP call. +.TP +\fB backup_initramfs +If set \fBupdate_initramfs\fP keeps an .bak file of the previous initramfs. If unset the backup initramfs will not be kept. + +.SH FILES +.TP +.I /etc/initramfs-tools/update-initramfs.conf + +.SH AUTHOR +The initramfs-tools are written by Maximilian Attems <maks@debian.org>, +Jeff Bailey <jbailey@raspberryginger.com> and numerous others. +.SH SEE ALSO +.BR +.IR initramfs.conf (5), +.IR initramfs-tools (7), +.IR mkinitramfs (8), +.IR update-initramfs (8). |