home · contact · privacy
Re-organize code, switch to explicit verbosity, fix efibootmgr boot label test.
authorPlom Heller <plom@plomlompom.com>
Tue, 25 Aug 2026 20:34:18 +0000 (22:34 +0200)
committerPlom Heller <plom@plomlompom.com>
Tue, 25 Aug 2026 20:34:18 +0000 (22:34 +0200)
install_debian.sh

index b3ca6e2aaaecc863583966129e166db7adddd1a0..8b57c744493a75f102ab306274bb52dfa7d3dd32 100755 (executable)
@@ -1,24 +1,6 @@
 #!/bin/sh
-set -Ceuvx
-
-die() {
-    echo "$*" >&2
-    exit 1
-}
-
-error() {
-    die "error: $*"
-}
-
-try_quiet() {
-    "$@" >/dev/null 2>&1
-}
-
-check_illegal_chars() {
-    case "$1" in *[!A-Za-z0-9_.-]*|"")
-        error "illegal characters in $2 '$1'" ;;
-    esac
-}
+set -Ceu
+SCRIPT_NAME=$0
 
 # constants unlikely to change
 PATH_DEV=/dev
@@ -33,11 +15,35 @@ PATH_BOOT_DEVICE="${PATH_DEV}/nvme0n1"
 IDX_BOOT_PARTITION=1
 PATH_MNT=/mnt/debinst
 
-# sanity checks: required tools
-for CMD in debootstrap pvcreate vgcreate lvcreate vgs efibootmgr; do
-    try_quiet command -v "${CMD}"\
-        || error "required tool not found: ${CMD}"
-done
+# helpers
+msg_nonl() {
+    printf '[## %s ##] ' "${SCRIPT_NAME}"
+    # shellcheck disable=SC2059
+    # (assume we'll always pass a literal format string)
+    printf "$@"
+}
+msg() {
+    msg_nonl "$@"
+    printf '\n'
+}
+die() {
+    msg '%s' "$*" >&2
+    exit 1
+}
+error() {
+    die "error: $*"
+}
+try_quiet() {
+    "$@" >/dev/null 2>&1
+}
+check_chars_legality() {
+    case "$1" in *[!A-Za-z0-9_.-]*|"")
+        error "illegal characters in $2 '$1'" ;;
+    esac
+}
+chroot_sh() {
+    LANG=C.UTF-8 chroot "${PATH_MNT}" /bin/sh -c "$@"
+}
 
 # inputs to confirm
 [ $# -eq 3 ]\
@@ -46,65 +52,77 @@ PARTITION=$1
 NAME_VOLGROUP=$2
 BOOT_LABEL=$3
 
+# constants derived from changeables
+LOGVOL_ROOT="${PATH_DEV}/${NAME_VOLGROUP}/${NAME_ROOT}"
+PATH_EFI_BOOT_LABEL="${PATH_EFI}/${BOOT_LABEL}"
+DEV_SLAVE="${PATH_MNT}${PATH_DEV}"
+
+# sanity checks: required tools
+for CMD in debootstrap efibootmgr lvcreate pvcreate vgcreate vgs; do
+    try_quiet command -v "${CMD}" ||\
+        error "required tool not found: ${CMD}"
+done
+
 # inputs sanity check: PARTITION
-[ -b "${PARTITION}" ]\
-    || error "${PARTITION} is not a block device"
-try_quiet findmnt --source "${PARTITION}"\
-    && error "${PARTITION} is already mounted"
+[ -b "${PARTITION}" ] ||\
+    error "${PARTITION} is not a block device"
+try_quiet findmnt --source "${PARTITION}" &&\
+    error "${PARTITION} is already mounted"
 # inputs sanity check: NAME_VOLGROUP
-check_illegal_chars "${NAME_VOLGROUP}" "volume group name"
-try_quiet vgs "${NAME_VOLGROUP}" \
-    && error "volume group '${NAME_VOLGROUP}' already exists"
+check_chars_legality "${NAME_VOLGROUP}" "volume group name"
+try_quiet vgs "${NAME_VOLGROUP}" &&\
+    error "volume group '${NAME_VOLGROUP}' already exists"
 # inputs sanity check: BOOT_LABEL
-check_illegal_chars "${BOOT_LABEL}" "boot label"
-[ -e "${PATH_EFI}/${BOOT_LABEL}" ] \
-    && error "${PATH_EFI}/${BOOT_LABEL} already exists"
+check_chars_legality "${BOOT_LABEL}" "boot label"
+[ -e "${PATH_EFI}/${BOOT_LABEL}" ] &&\
+    error "${PATH_EFI}/${BOOT_LABEL} already exists"
 efibootmgr \
-    | sed -n 's/^Boot[0-9A-Fa-f]\{4\}\*\{0,1\} //p' \
-    | grep -Fxq "${BOOT_LABEL}" \
-    && error "an EFI boot entry named '${BOOT_LABEL}' already exists"
+    | sed -n 's/^Boot[0-9A-Fa-f]\{4\}[* ] //p' \
+    | awk '{print $1}' \
+    | grep -Fxq "${BOOT_LABEL}" &&\
+    error "an EFI boot entry named '${BOOT_LABEL}' already exists"
 
 # run inputs by user and ask for confirmation
-echo "\
-target partition: [${PARTITION}] \
-name for volume group: [${NAME_VOLGROUP}] \
-boot label: [${BOOT_LABEL}]"
-printf "\
-this will erase %s – type YES! (all caps, \
-with exclamation mark) to continue: " "${PARTITION}"
-read CONFIRM
-[ "${CONFIRM}" = 'YES!' ]\
-    || die "aborted: confirmation not given"
-
-# constants derived from changeables
-LOGVOL_ROOT="${PATH_DEV}/${NAME_VOLGROUP}/${NAME_ROOT}"
-PATH_EFI_BOOT_LABEL="${PATH_EFI}/${BOOT_LABEL}"
-DEV_SLAVE="${PATH_MNT}${PATH_DEV}"
+msg 'Your installation setup choices:'
+msg '- target partition (WILL BE ERASED!): [ %s ]' "${PARTITION}"
+msg '- how to name new volume group: [ %s ]' "${NAME_VOLGROUP}"
+msg '- boot label to register with EFI: [ %s ]' "${BOOT_LABEL}"
+msg_nonl 'To continue, type "YES!" (all caps, exclamation mark, no quotes): '
+read -r CONFIRM
+[ "${CONFIRM}" = 'YES!' ] ||\
+    die 'ABORTED: expected confirmation not given.'
 
 # set up LVM and filesystem
+msg 'Initializing %s for LVM …' "${PARTITION}"
 pvcreate "${PARTITION}"
+msg 'Creating volume group "%s" there …' "${NAME_VOLGROUP}"
 vgcreate "${NAME_VOLGROUP}" "${PARTITION}"
+msg 'Creating logical volume "%s" there …' "${NAME_ROOT}"
 lvcreate -l '100%FREE' -n "${NAME_ROOT}" "${NAME_VOLGROUP}"
 mkfs.ext4 "${LOGVOL_ROOT}"
 
 # mount and install base
+msg 'Mounting %s at %s …' "${LOGVOL_ROOT}" "${PATH_MNT}"
 mkdir -p "${PATH_MNT}"
 mount "${LOGVOL_ROOT}" "${PATH_MNT}"
+msg 'Installing Debian Suite "%s" there via debootstrap …' "${DEB_SUITE}"
 debootstrap "${DEB_SUITE}" "${PATH_MNT}"
+msg 'For chroot environment also mounting %s into there …' "${PATH_DEV}"
 mount --rbind "${PATH_DEV}" "${DEV_SLAVE}"
 mount --make-rslave "${DEV_SLAVE}"
 
-# set up kernel, initrd, login
-LANG=C.UTF-8 chroot "${PATH_MNT}" /bin/sh -c "\
-    apt update &&\
-    apt install -y lvm2 linux-image-amd64 &&\
-    passwd"
+# set up kernel, initrd
+msg 'Into chroot environment installing LVM tools, kernel, initrd …'
+chroot_sh "apt update"
+chroot_sh "apt install -y lvm2 linux-image-amd64"
 
 # install kernel and initrd into EFI tree/vars
+msg 'EFI setup: copying kernel and initrd into %s …' "${PATH_EFI_BOOT_LABEL}"
 mkdir "${PATH_EFI_BOOT_LABEL}"
 for FILENAME in "${NAME_INITRD}" "${NAME_VMLINUZ}"; do
     cp "${PATH_MNT}/${FILENAME}" "${PATH_EFI_BOOT_LABEL}/"
 done
+msg 'EFI setup: adding boot entry %s …' "${BOOT_LABEL}"
 efibootmgr \
     --create \
     --disk "${PATH_BOOT_DEVICE}" \
@@ -113,6 +131,11 @@ efibootmgr \
     --loader "${BOOT_LABEL}/${NAME_VMLINUZ}" \
     --unicode "root=${LOGVOL_ROOT} ro initrd=${BOOT_LABEL}\\${NAME_INITRD}"
 
+# ask root login at latest possible moment, so that on fails: less left undone
+chroot_sh "passwd"
+
 # clean up mounts
+msg 'Mostly done! Now unmounting chroot environment …'
 umount -R "${DEV_SLAVE}"
 umount "${PATH_MNT}"
+msg 'Finished!'