refactor: set -eu

This commit is contained in:
Daniel Langbein 2023-03-16 16:14:17 +01:00
parent d2baa53624
commit 472659455e

View File

@ -1,12 +1,14 @@
#!/bin/bash #!/bin/bash
set -e
set -u
# load config # load config
source /etc/de-p1st-installer/installer.cfg || { exit 1; } source /etc/de-p1st-installer/installer.cfg
# load functions # load functions
source /usr/lib/de-p1st-installer/util.sh || { exit 1; } source /usr/lib/de-p1st-installer/util.sh
source /usr/lib/de-p1st-installer/user-input.sh || { exit 1; } source /usr/lib/de-p1st-installer/user-input.sh
source /usr/lib/de-p1st-installer/block-device.sh || { exit 1; } source /usr/lib/de-p1st-installer/block-device.sh
function main() { function main() {
# @pre # @pre
@ -14,59 +16,59 @@ function main() {
# @post # @post
# installation finished # installation finished
check_network || return $? check_network
system_time || return $? system_time
# in: BOOT_FIRMWARE, FS, HOSTNAME, USERNAME, USER_PWD, FDE, LUKS_PWD; (all variables are optional) # in: BOOT_FIRMWARE, FS, HOSTNAME, USERNAME, USER_PWD, FDE, LUKS_PWD; (all variables are optional)
# out: BOOT_FIRMWARE, FS, HOSTNAME, USERNAME, USER_PWD, FDE, LUKS_PWD (if FDE='true') # out: BOOT_FIRMWARE, FS, HOSTNAME, USERNAME, USER_PWD, FDE, LUKS_PWD (if FDE='true')
get_user_input || return $? get_user_input
# in: CPU_VENDOR (optional) # in: CPU_VENDOR (optional)
# out: CPU_VENDOR # out: CPU_VENDOR
get_cpu_vendor || return $? get_cpu_vendor
# in: FS # in: FS
# out: FS_DEFAULT_MOUNT_OPTIONS # out: FS_DEFAULT_MOUNT_OPTIONS
get_default_mount_options || return $? get_default_mount_options
# in: FS # in: FS
# out: FS_ADDITIONAL_MOUNT_OPTIONS # out: FS_ADDITIONAL_MOUNT_OPTIONS
get_additional_mount_options || return $? get_additional_mount_options
# in: TARGET_BLOCK_DEVICE, BOOT_FIRMWARE # in: TARGET_BLOCK_DEVICE, BOOT_FIRMWARE
# out: BOOT_PART, LUKS_PART # out: BOOT_PART, LUKS_PART
partition || return $? partition
# in: BOOT_FIRMWARE, BOOT_PART, LUKS_PART, FDE, LUKS_PWD, FS # in: BOOT_FIRMWARE, BOOT_PART, LUKS_PART, FDE, LUKS_PWD, FS
# out: LUKS_PART_UUID (if FDE='true'), DATA_PART # out: LUKS_PART_UUID (if FDE='true'), DATA_PART
format || return $? format
# Combine default and additional mount options # Combine default and additional mount options
# out: FS_MOUNT_OPTIONS # out: FS_MOUNT_OPTIONS
{ {
TMP1=("${FS_DEFAULT_MOUNT_OPTIONS[@]}" "${FS_ADDITIONAL_MOUNT_OPTIONS[@]}") || return $? TMP1=("${FS_DEFAULT_MOUNT_OPTIONS[@]}" "${FS_ADDITIONAL_MOUNT_OPTIONS[@]}")
# Join array elements by "," # Join array elements by ","
join_by ',' TMP1 FS_MOUNT_OPTIONS || return $? join_by ',' TMP1 FS_MOUNT_OPTIONS
} }
mount_partitions || return $? mount_partitions
# in: BOOT_FIRMWARE, PACSTRAP_INTERACTIVE (optional) # in: BOOT_FIRMWARE, PACSTRAP_INTERACTIVE (optional)
run_pacstrap || return $? run_pacstrap
# in: FS # in: FS
run_genfstab || return $? run_genfstab
# in: HOSTNAME, FQDN (optional), STATIC_IP (optional), IPV6_CAPABLE (optional) # in: HOSTNAME, FQDN (optional), STATIC_IP (optional), IPV6_CAPABLE (optional)
config_hostname_and_hosts || return $? config_hostname_and_hosts
# in: USERNAME, USER_PWD, ROOT_PWD (optional) # in: USERNAME, USER_PWD, ROOT_PWD (optional)
user_and_pwd || return $? user_and_pwd
sudo arch-chroot /mnt mkinitcpio -P || return $? sudo arch-chroot /mnt mkinitcpio -P
# in: TARGET_BLOCK_DEVICE, FDE, LUKS_PART_UUID # in: TARGET_BLOCK_DEVICE, FDE, LUKS_PART_UUID
bootloader || return $? bootloader
if [ "${LEAVE_MOUNTED}" = 'true' ]; then if [ "${LEAVE_MOUNTED}" = 'true' ]; then
echo 'Leaving partitions below /mnt mounted and '"${DATA_PART}"' opened.' echo 'Leaving partitions below /mnt mounted and '"${DATA_PART}"' opened.'
else else
sudo umount -R /mnt || return $? sudo umount -R /mnt
if [ "${FDE}" = 'true' ]; then if [ "${FDE}" = 'true' ]; then
sudo cryptsetup luksClose "$(basename "${DATA_PART}")" || return $? sudo cryptsetup luksClose "$(basename "${DATA_PART}")"
fi fi
fi fi
echo 'Finished installation without errors!' echo 'Finished installation without errors!'
@ -96,7 +98,7 @@ function increase_cow_space() {
} }
echo 'Increasing cowspace partition of live medium ...' echo 'Increasing cowspace partition of live medium ...'
sudo mount -o remount,size=2G /run/archiso/cowspace || return $? sudo mount -o remount,size=2G /run/archiso/cowspace
} }
function get_user_input() { function get_user_input() {
@ -109,8 +111,8 @@ function get_user_input() {
# FDE: 'true' | 'false' # FDE: 'true' | 'false'
# LUKS_PWD: only set if FDE='true' # LUKS_PWD: only set if FDE='true'
get_block_devices_with_size || return $? get_block_devices_with_size
single_choice_if_empty TARGET_BLOCK_DEVICE 'Select target device for installation' BLOCK_DEVICE_SIZES || return $? single_choice_if_empty TARGET_BLOCK_DEVICE 'Select target device for installation' BLOCK_DEVICE_SIZES
if [ "${BOOT_FIRMWARE}" = 'autodetect' ]; then if [ "${BOOT_FIRMWARE}" = 'autodetect' ]; then
# Detect boot firmware type: https://askubuntu.com/a/162573 # Detect boot firmware type: https://askubuntu.com/a/162573
@ -128,43 +130,43 @@ function get_user_input() {
else # If $BOOT_FIRMWARE is empty: Let user select BIOS type else # If $BOOT_FIRMWARE is empty: Let user select BIOS type
TMP1=('uefi' 'Newer mainboards' \ TMP1=('uefi' 'Newer mainboards' \
'bios' 'Legacy BIOS on older mainboards') 'bios' 'Legacy BIOS on older mainboards')
single_choice_if_empty BOOT_FIRMWARE 'Select your bios type' TMP1 || return $? single_choice_if_empty BOOT_FIRMWARE 'Select your bios type' TMP1
fi fi
TMP1=('BTRFS' 'Allows snapshots and dynamic extension of the FS' \ TMP1=('BTRFS' 'Allows snapshots and dynamic extension of the FS' \
'EXT4' 'Default FS of many distributions' \ 'EXT4' 'Default FS of many distributions' \
'F2FS' 'Flash-Friendly-FS for SSD or NVMe') 'F2FS' 'Flash-Friendly-FS for SSD or NVMe')
single_choice_if_empty FS 'Select filesystem to use' TMP1 || return $? single_choice_if_empty FS 'Select filesystem to use' TMP1
if [ "${FS}" = 'BTRFS' ]; then if [ "${FS}" = 'BTRFS' ]; then
TMP1=('root_only' 'Just one subvolume for "/".' \ TMP1=('root_only' 'Just one subvolume for "/".' \
'@root@home' 'Two subvolumes @ and @home. This configuration allows usage of "Timeshift".') '@root@home' 'Two subvolumes @ and @home. This configuration allows usage of "Timeshift".')
single_choice_if_empty FS_BTRFS_SUBVOL_LAYOUT 'Select your preferred subvolume layout' TMP1 || return $? single_choice_if_empty FS_BTRFS_SUBVOL_LAYOUT 'Select your preferred subvolume layout' TMP1
fi fi
ask_user_if_empty HOSTNAME 'Enter hostname:' || return $? ask_user_if_empty HOSTNAME 'Enter hostname:'
ask_user_if_empty USERNAME 'Enter username:' || return $? ask_user_if_empty USERNAME 'Enter username:'
if [ -z "${USER_PWD}" ]; then if [ -z "${USER_PWD}" ]; then
ask_user_if_empty USER_PWD 'Enter a user password:' || return $? ask_user_if_empty USER_PWD 'Enter a user password:'
ask_user_if_empty USER_PWD2 'Please enter the password again:' || return $? ask_user_if_empty USER_PWD2 'Please enter the password again:'
# shellcheck disable=SC2153 # shellcheck disable=SC2153
[[ "${USER_PWD}" == "${USER_PWD2}" ]] || { [[ "${USER_PWD}" == "${USER_PWD2}" ]] || {
echo 'Passwords did not match'; echo 'Passwords did not match'
exit 1; exit 1
} }
fi fi
TMP1=('true' 'Yes' 'false' 'No') TMP1=('true' 'Yes' 'false' 'No')
single_choice_if_empty FDE 'Shall Full-Disk-Encryption be enabled?' TMP1 || return $? single_choice_if_empty FDE 'Shall Full-Disk-Encryption be enabled?' TMP1
if [ "${FDE}" = 'true' ] && [ -z "${LUKS_PWD}" ]; then if [ "${FDE}" = 'true' ] && [ -z "${LUKS_PWD}" ]; then
ask_user_if_empty LUKS_PWD 'Enter a disk encryption password:' || return $? ask_user_if_empty LUKS_PWD 'Enter a disk encryption password:'
ask_user_if_empty LUKS_PWD2 'Please enter the password again:' || return $? ask_user_if_empty LUKS_PWD2 'Please enter the password again:'
# shellcheck disable=SC2153 # shellcheck disable=SC2153
[[ "${LUKS_PWD}" == "${LUKS_PWD2}" ]] || { [[ "${LUKS_PWD}" == "${LUKS_PWD2}" ]] || {
echo 'Passwords did not match'; echo 'Passwords did not match'
exit 1; exit 1
} }
fi fi
} }
@ -233,7 +235,7 @@ function get_additional_mount_options() {
;; ;;
esac esac
multi_choice_if_empty FS_ADDITIONAL_MOUNT_OPTIONS 'Select mount options' TMP1 || return $? multi_choice_if_empty FS_ADDITIONAL_MOUNT_OPTIONS 'Select mount options' TMP1
} }
function mount_partitions() { function mount_partitions() {
@ -245,26 +247,26 @@ function mount_partitions() {
'root_only') 'root_only')
# Nothing special; same steps as for a regular FS # Nothing special; same steps as for a regular FS
echo 'Mounting data partition with options: '"${FS_MOUNT_OPTIONS}" echo 'Mounting data partition with options: '"${FS_MOUNT_OPTIONS}"
sudo mount -o "${FS_MOUNT_OPTIONS}" "${DATA_PART}" /mnt || return $? sudo mount -o "${FS_MOUNT_OPTIONS}" "${DATA_PART}" /mnt
;; ;;
'@root@home') '@root@home')
# Timeshift BTRFS subvol layout: # Timeshift BTRFS subvol layout:
# https://github.com/teejee2008/timeshift#supported-system-configurations # https://github.com/teejee2008/timeshift#supported-system-configurations
# Mount top level subvolume # Mount top level subvolume
sudo mount -o subvolid=5 "${DATA_PART}" /mnt || return $? sudo mount -o subvolid=5 "${DATA_PART}" /mnt
# Create subvolumes @ and @home # Create subvolumes @ and @home
sudo btrfs subvolume create /mnt/@ || return $? sudo btrfs subvolume create /mnt/@
sudo btrfs subvolume create /mnt/@home || return $? sudo btrfs subvolume create /mnt/@home
# List the created subvolumes # List the created subvolumes
sudo btrfs subvolume list /mnt || return $? sudo btrfs subvolume list /mnt
# Umount the top level subvolume # Umount the top level subvolume
sudo umount -R /mnt || return $? sudo umount -R /mnt
echo 'Mounting @ and @home subvolumes with options: '"${FS_MOUNT_OPTIONS}" echo 'Mounting @ and @home subvolumes with options: '"${FS_MOUNT_OPTIONS}"
sudo mount -o 'subvol=@,'"${FS_MOUNT_OPTIONS}" "${DATA_PART}" /mnt || return $? sudo mount -o 'subvol=@,'"${FS_MOUNT_OPTIONS}" "${DATA_PART}" /mnt
sudo mkdir /mnt/home || return $? sudo mkdir /mnt/home
sudo mount -o 'subvol=@home,'"${FS_MOUNT_OPTIONS}" "${DATA_PART}" /mnt/home || return $? sudo mount -o 'subvol=@home,'"${FS_MOUNT_OPTIONS}" "${DATA_PART}" /mnt/home
;; ;;
*) *)
echo 'BTRFS subvolume layout '"${FS_BTRFS_SUBVOL_LAYOUT}"' not supported!' echo 'BTRFS subvolume layout '"${FS_BTRFS_SUBVOL_LAYOUT}"' not supported!'
@ -273,12 +275,12 @@ function mount_partitions() {
esac esac
else else
echo 'Mounting data partition with options: '"${FS_MOUNT_OPTIONS}" echo 'Mounting data partition with options: '"${FS_MOUNT_OPTIONS}"
sudo mount -o "${FS_MOUNT_OPTIONS}" "${DATA_PART}" /mnt || return $? sudo mount -o "${FS_MOUNT_OPTIONS}" "${DATA_PART}" /mnt
fi fi
echo 'Mounting boot partition ...' echo 'Mounting boot partition ...'
sudo mkdir /mnt/boot || return $? sudo mkdir /mnt/boot
sudo mount "${BOOT_PART}" /mnt/boot || return $? sudo mount "${BOOT_PART}" /mnt/boot
} }
function run_pacstrap() { function run_pacstrap() {
@ -328,7 +330,7 @@ function run_pacstrap() {
fi fi
args+=('/mnt') args+=('/mnt')
sudo pacstrap "${args[@]}" "${PKGS[@]}" || return $? sudo pacstrap "${args[@]}" "${PKGS[@]}"
} }
function run_genfstab() { function run_genfstab() {
@ -342,7 +344,7 @@ function run_genfstab() {
case "${FS}" in case "${FS}" in
BTRFS) BTRFS)
# Remove "subvolid=..." mount option but leave "subvol=..." mount option # Remove "subvolid=..." mount option but leave "subvol=..." mount option
fstab=$(printf '%s' "${fstab}" | sed 's/,subvolid=[^,\s]\+//') || return $? fstab=$(printf '%s' "${fstab}" | sed 's/,subvolid=[^,\s]\+//')
# Check if fstab does still contain subvolid mount option # Check if fstab does still contain subvolid mount option
if printf '%s' "${fstab}" | grep -q 'subvolid='; then if printf '%s' "${fstab}" | grep -q 'subvolid='; then
echo 'This should not happen!' echo 'This should not happen!'
@ -361,7 +363,7 @@ function run_genfstab() {
;; ;;
esac esac
printf '%s' "${fstab}" | sudo tee /mnt/etc/fstab >/dev/null || return $? printf '%s' "${fstab}" | sudo tee /mnt/etc/fstab >/dev/null
} }
function config_hostname_and_hosts() { function config_hostname_and_hosts() {
@ -372,7 +374,7 @@ function config_hostname_and_hosts() {
# IPV6_CAPABLE: optional, 'true' # IPV6_CAPABLE: optional, 'true'
echo 'Set hostname ...' echo 'Set hostname ...'
echo "${HOSTNAME}" | sudo tee /mnt/etc/hostname >/dev/null || return $? echo "${HOSTNAME}" | sudo tee /mnt/etc/hostname >/dev/null
echo 'Create hosts file ...' echo 'Create hosts file ...'
# If the system has a permanent IP address, it should be used instead of 127.0.1.1. # If the system has a permanent IP address, it should be used instead of 127.0.1.1.
@ -389,14 +391,14 @@ function config_hostname_and_hosts() {
echo '# The following lines are desirable for IPv4 capable hosts echo '# The following lines are desirable for IPv4 capable hosts
127.0.0.1 localhost 127.0.0.1 localhost
# 127.0.1.1 is often used for the FQDN of the machine # 127.0.1.1 is often used for the FQDN of the machine
'"${STATIC_IP} ${FQDN} ${HOSTNAME}" | sudo tee /mnt/etc/hosts >/dev/null || return $? '"${STATIC_IP} ${FQDN} ${HOSTNAME}" | sudo tee /mnt/etc/hosts >/dev/null
if [ "${IPV6_CAPABLE}" = 'true' ]; then if [ "${IPV6_CAPABLE}" = 'true' ]; then
echo ' echo '
# The following lines are desirable for IPv6 capable hosts # The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback ::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes ff02::1 ip6-allnodes
ff02::2 ip6-allrouters' | sudo tee -a /mnt/etc/hosts >/dev/null || return $? ff02::2 ip6-allrouters' | sudo tee -a /mnt/etc/hosts >/dev/null
fi fi
} }
@ -409,14 +411,14 @@ function user_and_pwd() {
echo 'Adding user and changing shell to /bin/zsh ...' echo 'Adding user and changing shell to /bin/zsh ...'
# -m: create home # -m: create home
# -U: Create a group with the same name as the user, and add the user to this group. # -U: Create a group with the same name as the user, and add the user to this group.
sudo arch-chroot /mnt useradd -m -s /usr/bin/zsh -g wheel "${USERNAME}" || return $? sudo arch-chroot /mnt useradd -m -s /usr/bin/zsh -g wheel "${USERNAME}"
sudo arch-chroot /mnt chsh -s /usr/bin/zsh || return $? sudo arch-chroot /mnt chsh -s /usr/bin/zsh
# If ROOT_PWD is not given, the use USER_PWD for root user # If ROOT_PWD is not given, the use USER_PWD for root user
ROOT_PWD="${ROOT_PWD:="${USER_PWD}"}" ROOT_PWD="${ROOT_PWD:="${USER_PWD}"}"
printf '%s:%s' "${USERNAME}" "${USER_PWD}" | sudo chpasswd --root /mnt || return $? printf '%s:%s' "${USERNAME}" "${USER_PWD}" | sudo chpasswd --root /mnt
printf '%s:%s' "root" "${ROOT_PWD}" | sudo chpasswd --root /mnt || return $? printf '%s:%s' "root" "${ROOT_PWD}" | sudo chpasswd --root /mnt
} }
function bootloader() { function bootloader() {
@ -431,10 +433,10 @@ function bootloader() {
# portable fallback efi name for grub: # portable fallback efi name for grub:
# * https://www.rodsbooks.com/efi-bootloaders/installation.html#alternative-naming # * https://www.rodsbooks.com/efi-bootloaders/installation.html#alternative-naming
# * arch-chroot /mnt cp /boot/EFI/GRUB/grubx64.efi /boot/EFI/BOOT/bootx64.efi # * arch-chroot /mnt cp /boot/EFI/GRUB/grubx64.efi /boot/EFI/BOOT/bootx64.efi
sudo arch-chroot /mnt grub-install --target=x86_64-efi --bootloader-id=GRUB --efi-directory=/boot --removable || return $? sudo arch-chroot /mnt grub-install --target=x86_64-efi --bootloader-id=GRUB --efi-directory=/boot --removable
;; ;;
bios) bios)
sudo arch-chroot /mnt grub-install --target=i386-pc "${TARGET_BLOCK_DEVICE}" || return $? sudo arch-chroot /mnt grub-install --target=i386-pc "${TARGET_BLOCK_DEVICE}"
;; ;;
*) *)
echo 'Not yet implemented!' echo 'Not yet implemented!'
@ -455,14 +457,14 @@ function bootloader() {
# Use filename .../20- for the holoscript so that it gets executed after the one from de-p1st-grub # Use filename .../20- for the holoscript so that it gets executed after the one from de-p1st-grub
local holoScriptDir=/mnt/usr/share/holo/files/20-de-p1st-installer/etc/default/ local holoScriptDir=/mnt/usr/share/holo/files/20-de-p1st-installer/etc/default/
# The holoscript shall contain one 'sed "..."' command # The holoscript shall contain one 'sed "..."' command
sudo mkdir -p "${holoScriptDir}" || return $? sudo mkdir -p "${holoScriptDir}"
sudo echo '#!/bin/sh sudo echo '#!/bin/sh
sed "s|^GRUB_CMDLINE_LINUX=\"\"\$|GRUB_CMDLINE_LINUX=\"cryptdevice=/dev/disk/by-uuid/'"${LUKS_PART_UUID}"':crypt\"|"' \ sed "s|^GRUB_CMDLINE_LINUX=\"\"\$|GRUB_CMDLINE_LINUX=\"cryptdevice=/dev/disk/by-uuid/'"${LUKS_PART_UUID}"':crypt\"|"' \
| sudo tee "${holoScriptDir}"/grub.holoscript || return $? | sudo tee "${holoScriptDir}"/grub.holoscript
sudo chmod 0544 "${holoScriptDir}"/grub.holoscript || return $? sudo chmod 0544 "${holoScriptDir}"/grub.holoscript
} }
# Then we apply the holoscript # Then we apply the holoscript
sudo arch-chroot /mnt holo apply --force file:/etc/default/grub || return $? sudo arch-chroot /mnt holo apply --force file:/etc/default/grub
;; ;;
false) false)
true true
@ -474,7 +476,7 @@ sed "s|^GRUB_CMDLINE_LINUX=\"\"\$|GRUB_CMDLINE_LINUX=\"cryptdevice=/dev/disk/by-
esac esac
# And finally run grub-mkconfig # And finally run grub-mkconfig
sudo arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg || return $? sudo arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg
} }
} }