You are not logged in.
I recently created an installation program for my own use at home. It works but I ran into an issue with a case statement. I found a solution but I am not sure why it works. Originally I tried to call the partitioning function and then set the four variables ($boot, $spare, $root1, $root2) before calling the next function. If I do that the script will fail because only three of the four variables will get set. The fourth variable ($root2) will be unset. Once I found that out I moved the function call to create the boot partition up and now all four variables are getting set. I am not a programmer and I cannot see why this is an issue.
What did I miss?
case "$mode:$disk1:$disk2" in
bios:/dev/sd?:/dev/sd?)
bios_partitions
boot=${disk1}2
spare=${disk2}2
create_bios_boot
root1=$(lsblk -dno PARTUUID ${disk1}3)
root2=$(lsblk -dno PARTUUID ${disk2}3)
;;
bios:/dev/nvme?n?:/dev/nvme?n?)
bios_partitions
boot=${disk1}p2
spare=${disk2}p2
create_bios_boot
root1=$(lsblk -dno PARTUUID ${disk1}p3)
root2=$(lsblk -dno PARTUUID ${disk2}p3)
;;
uefi:/dev/sd?:/dev/sd?)
uefi_partitions
boot=${disk1}1
spare=${disk2}1
create_uefi_boot
root1=$(lsblk -dno PARTUUID ${disk1}2)
root2=$(lsblk -dno PARTUUID ${disk2}2)
;;
uefi:/dev/nvme?n?:/dev/nvme?n?)
uefi_partitions
boot=${disk1}p1
spare=${disk2}p1
create_uefi_boot
root1=$(lsblk -dno PARTUUID ${disk1}p2)
root2=$(lsblk -dno PARTUUID ${disk2}p2)
;;
*)
print "usage: archzfs disk1 disk2 mode"
print "disks = '/dev/sd?' | '/dev/nvme?n?'"
print "mode = 'uefi' | 'bios'"
exit
esac
UPDATE:
The issue was with my partition tables not being updated.
Following partitioning the kernel was not being updated.
When setting variables the needed information was not available.
I did two things:
1) added 'parted $disk1 mklabel gpt' to the end of my disk wiping function
2) added 'partprobe -s $disk1' to the end of my disk partitioning function
Last edited by lenhuppe (2021-05-14 21:33:30)
"I'm suspicious of people who don't like dogs, but I trust a dog when it doesn't like a person." -- Bill Murray
Offline
Is this the working example? It would help to know what the non-working example looked like, and also what exactly bios_partitions/create_bios_boot (and their EFI equivalents) do.
But my guess from this code is that $root2 wasn't actually unset, but rather simply set to an empty value, because lsblk didn't produce any output, because the partition didn't exist, because it was only created by whatever those two function do.
I would generally recommend handling errors correctly instead of just ignoring them, otherwise your program will show undefined behaviour (as it continues as if everything is alright).
For example
if ! root2=$(lsblk -dno PARTUUID ${disk2}3); then
# handle error here
fi
or
root2=$(lsblk -dno PARTUUID ${disk2}3) || {
# handle error here, with $? containing the return code of the command
}
Offline
Is this the working example? It would help to know what the non-working example looked like, and also what exactly bios_partitions/create_bios_boot (and their EFI equivalents) do.
But my guess from this code is that $root2 wasn't actually unset, but rather simply set to an empty value, because lsblk didn't produce any output, because the partition didn't exist, because it was only created by whatever those two function do.
I would generally recommend handling errors correctly instead of just ignoring them, otherwise your program will show undefined behaviour (as it continues as if everything is alright).
For exampleif ! root2=$(lsblk -dno PARTUUID ${disk2}3); then # handle error here fi
or
root2=$(lsblk -dno PARTUUID ${disk2}3) || { # handle error here, with $? containing the return code of the command }
Error handling is sound advice. This one has me stumped. The case statement in question is the first thing under MAIN near the bottom of my script.
Here is what I have at the moment:
archzfs working version
#!/usr/bin/env bash
set -e
#
# Capture args
#
disk1="${1}"
disk2="${2}"
mode="${3}"
#
# variables used
#
#language=en
timezone=America/New_York
countrycode=US
country=us
kernel=linux-lts
#
# print messages
#
function print {
echo -e '\n\t\033[0;32m' $1 '\033[0m\n'
}
#
# set locale + date & time + system clock
#
function set_locale {
clear
print "Welcome to the Arch Linux on OpenZFS installation program"
print "Syncronizng with the network time server"
timedatectl set-ntp true && sleep 30
timedatectl set-local-rtc 0
timedatectl set-timezone $timezone
hwclock --systohc
echo -e '\n'
timedatectl
localectl set-locale en_$countrycode.UTF-8
localectl set-keymap $country
echo -e '\n'
localectl
}
#
# wipe drives
#
# lba: 512 bytes zpool ashift=12
# lba: 4096 bytes zpool ashift=9
#
function wipe_drives {
print "Wiping drives"
case $disk1 in
/dev/nvme?n1)
#
# nvme id-ns /dev/nvme?n? | grep lba
# nlbaf label of lba format being used 0 = first one
# lbaf qty of lba formats supported 0 = qty one
# lbads logical block addressing size 9 = 512 bytes, 12 = 4096 bytes
#
# nuclear option:
# nvme delete-ns /dev/nvme?n?
# nvme create-ns /dev/nvme?
#
blkdiscard -f $disk1
nvme format -f $disk1
blkdiscard -f $disk2
nvme format -f $disk2
;;
/dev/sd?)
#
# hdparm -I /dev/sd? | grep size
# Logical Sector size: 512 bytes
# Physical Sector size: 512 bytes
#
blkdiscard -f $disk1
blkdiscard -f $disk2
;;
esac
}
#
# UEFI Partitions
#
function uefi_partitions {
print "Partitioning drives for UEFI system"
sgdisk -n 0:1M:+512M -t 0:EF00 $disk1
sgdisk -n 0:0:-0M -t 0:BF00 $disk1
sgdisk -G $disk1
sgdisk -n 0:1M:+512M -t 0:EF00 $disk2
sgdisk -n 0:0:-0M -t 0:BF00 $disk2
sgdisk -G $disk2
}
#
# BIOS Partitions
#
function bios_partitions {
print "Partitioning drives for BIOS system"
sgdisk -n 0:0:+2MiB -t 0:ef02 $disk1
sgdisk -n 0:0:+512MiB -t 0:8300 $disk1
sgdisk -n 0:0:-0MiB -t 0:bf00 $disk1
sgdisk -G $disk1
sgdisk -n 0:0:+2MiB -t 0:ef02 $disk2
sgdisk -n 0:0:+512MiB -t 0:8300 $disk2
sgdisk -n 0:0:-0MiB -t 0:bf00 $disk2
sgdisk -G $disk2
}
#
# UEFI boot partition
#
function create_uefi_boot {
print "Creating UEFI boot partition $boot"
mkfs.fat -F 32 -n EFI $boot
}
#
# BIOS boot partition
#
function create_bios_boot {
print "Creating BIOS boot partition $boot"
mkfs.ext4 -L BOOT $boot
}
#
# Mirrored zpool
#
# -o pool_property=value
# -o pool_feature@...=value
# -O file-system-property=value
#
zpool_options=(
-f
-d
-m none
-R /mnt
-o ashift=12
-o autotrim=on
-o feature@lz4_compress=enabled
-O compression=lz4
-O relatime=on
-O atime=off
-O dnodesize=legacy
-O normalization=formD
-O devices=off
-O xattr=sa
)
function create_pool {
print "Creating ZFS pool zroot"
zpool create ${zpool_options[*]} zroot mirror $root1 $root2
zpool status
}
#
# Datasets
#
function create_datasets {
print "Creating datasets"
zfs create -o canmount=off -o mountpoint=none zroot/ROOT
zfs create -o canmount=noauto -o mountpoint=/ zroot/ROOT/default
zfs create -o canmount=off -o mountpoint=none zroot/data
zfs create -o mountpoint=/home zroot/data/home
zfs create -o mountpoint=/root zroot/data/root
zfs create -o mountpoint=/archive zroot/data/archive
zpool set bootfs=zroot/ROOT/default zroot
zfs list
}
#
# Mount everything
#
function mount_all {
print "Mounting everything"
zfs umount -a
zpool export zroot
zpool import -d /dev/disk/by-partuuid/ -R /mnt zroot -N
zfs mount zroot/ROOT/default
zfs mount -a
mkdir /mnt/boot
mount $boot /mnt/boot
}
#
# Base installation
#
base_pkgs=(
base
$kernel
$kernel-headers
linux-firmware
)
function install_base {
print "Installing Arch Linux"
pacstrap /mnt ${base_pkgs[*]}
genfstab -U -p /mnt >> /mnt/etc/fstab
sed -i 's/^zroot/#zroot/' /mnt/etc/fstab
mkdir /mnt/archive/archzfs
cp /usr/local/bin/* /mnt/archive/archzfs
arch-chroot /mnt /archive/archzfs/chroot_config $mode $disk1 $kernel $timezone $countrycode $country
}
#
# Finish before rebooting
#
function umount_all {
print "Unmounting everything"
umount /mnt/boot
umount -R /mnt
zfs umount -a && zpool export zroot && print "Arch Linux on OpenZFS installation complete"
}
#### ----- MAIN ---- ####
# there are four possible scenarios:
#
# SSD /dev/sd? NVMe /dev/nvme?n1
#
# UEFI <disk1>1 = $boot <disk1>p1 = $boot
# <disk1>2 = $root1 <disk1>p2 = $root1
# <disk2>1 = $spare <disk2>p1 = $spare
# <disk2>2 = $root2 <disk2>p2 = $root2
#
# BIOS <disk1>1 = bios-boot <disk1>p1 = bios-boot
# <disk1>2 = $boot <disk1>p2 = $boot
# <disk1>3 = $root1 <disk1>p3 = $root1
# <disk2>1 = unused <disk2>p1 = unused
# <disk2>2 = $spare <disk2>p2 = $spare
# <disk2>3 = $root2 <disk2>p3 = $root2
#
# $boot is mounted at /boot and used as an efi or grub partition
# $root1 and $root2 form the zpool mirror where the root partition lies
# bios-boot is used by by the system bios to find the grub partition
#
# what to do with $spare ?
#
# validate input with case before proceding
#
case "$mode:$disk1:$disk2" in
bios:/dev/sd?:/dev/sd?)
set_locale
wipe_drives
bios_partitions
boot=${disk1}2
spare=${disk2}2
create_bios_boot <-- this was moved up from the bottom
root1=$(lsblk -dno PARTUUID ${disk1}3)
root2=$(lsblk -dno PARTUUID ${disk2}3)
;;
bios:/dev/nvme?n?:/dev/nvme?n?)
set_locale
wipe_drives
bios_partitions
boot=${disk1}p2
spare=${disk2}p2
create_bios_boot <-- this was moved up from the bottom
root1=$(lsblk -dno PARTUUID ${disk1}p3)
root2=$(lsblk -dno PARTUUID ${disk2}p3)
;;
uefi:/dev/sd?:/dev/sd?)
set_locale
wipe_drives
uefi_partitions
boot=${disk1}1
spare=${disk2}1
create_uefi_boot <-- this was moved up from the bottom
root1=$(lsblk -dno PARTUUID ${disk1}2)
root2=$(lsblk -dno PARTUUID ${disk2}2)
;;
uefi:/dev/nvme?n?:/dev/nvme?n?)
set_locale
wipe_drives
uefi_partitions
boot=${disk1}p1
spare=${disk2}p1
create_uefi_boot <-- this was moved up from the bottom
root1=$(lsblk -dno PARTUUID ${disk1}p2)
root2=$(lsblk -dno PARTUUID ${disk2}p2)
;;
*)
print "usage: archzfs disk1 disk2 mode"
print "disks = '/dev/sd?' | '/dev/nvme?n?'"
print "mode = 'uefi' | 'bios'"
exit
esac
create_pool
create_datasets
mount_all
install_base
umount_all
Here is where I had an issue:
archzfs nonworking version
#!/usr/bin/env bash
set -e
#
# Capture args
#
disk1="${1}"
disk2="${2}"
mode="${3}"
#
# variables used
#
#language=en
timezone=America/New_York
countrycode=US
country=us
kernel=linux-lts
#
# print messages
#
function print {
echo -e '\n\t\033[0;32m' $1 '\033[0m\n'
}
#
# set locale + date & time + system clock
#
function set_locale {
clear
print "Welcome to the Arch Linux on OpenZFS installation program"
print "Syncronizng with the network time server"
timedatectl set-ntp true && sleep 30
timedatectl set-local-rtc 0
timedatectl set-timezone $timezone
hwclock --systohc
echo -e '\n'
timedatectl
localectl set-locale en_$countrycode.UTF-8
localectl set-keymap $country
echo -e '\n'
localectl
}
#
# wipe drives
#
# lba: 512 bytes zpool ashift=12
# lba: 4096 bytes zpool ashift=9
#
function wipe_drives {
print "Wiping drives"
case $disk1 in
/dev/nvme?n1)
#
# nvme id-ns /dev/nvme?n? | grep lba
# nlbaf label of lba format being used 0 = first one
# lbaf qty of lba formats supported 0 = qty one
# lbads logical block addressing size 9 = 512 bytes, 12 = 4096 bytes
#
# nuclear option:
# nvme delete-ns /dev/nvme?n?
# nvme create-ns /dev/nvme?
#
blkdiscard -f $disk1
nvme format -f $disk1
blkdiscard -f $disk2
nvme format -f $disk2
;;
/dev/sd?)
#
# hdparm -I /dev/sd? | grep size
# Logical Sector size: 512 bytes
# Physical Sector size: 512 bytes
#
blkdiscard -f $disk1
blkdiscard -f $disk2
;;
esac
}
#
# UEFI Partitions
#
function uefi_partitions {
print "Partitioning drives for UEFI system"
sgdisk -n 0:1M:+512M -t 0:EF00 $disk1
sgdisk -n 0:0:-0M -t 0:BF00 $disk1
sgdisk -G $disk1
sgdisk -n 0:1M:+512M -t 0:EF00 $disk2
sgdisk -n 0:0:-0M -t 0:BF00 $disk2
sgdisk -G $disk2
}
#
# BIOS Partitions
#
function bios_partitions {
print "Partitioning drives for BIOS system"
sgdisk -n 0:0:+2MiB -t 0:ef02 $disk1
sgdisk -n 0:0:+512MiB -t 0:8300 $disk1
sgdisk -n 0:0:-0MiB -t 0:bf00 $disk1
sgdisk -G $disk1
sgdisk -n 0:0:+2MiB -t 0:ef02 $disk2
sgdisk -n 0:0:+512MiB -t 0:8300 $disk2
sgdisk -n 0:0:-0MiB -t 0:bf00 $disk2
sgdisk -G $disk2
}
#
# UEFI boot partition
#
function create_uefi_boot {
print "Creating UEFI boot partition $boot"
mkfs.fat -F 32 -n EFI $boot
}
#
# BIOS boot partition
#
function create_bios_boot {
print "Creating BIOS boot partition $boot"
mkfs.ext4 -L BOOT $boot
}
#
# Mirrored zpool
#
# -o pool_property=value
# -o pool_feature@...=value
# -O file-system-property=value
#
zpool_options=(
-f
-d
-m none
-R /mnt
-o ashift=12
-o autotrim=on
-o feature@lz4_compress=enabled
-O compression=lz4
-O relatime=on
-O atime=off
-O dnodesize=legacy
-O normalization=formD
-O devices=off
-O xattr=sa
)
function create_pool {
print "Creating ZFS pool zroot"
zpool create ${zpool_options[*]} zroot mirror $root1 $root2
zpool status
}
#
# Datasets
#
function create_datasets {
print "Creating datasets"
zfs create -o canmount=off -o mountpoint=none zroot/ROOT
zfs create -o canmount=noauto -o mountpoint=/ zroot/ROOT/default
zfs create -o canmount=off -o mountpoint=none zroot/data
zfs create -o mountpoint=/home zroot/data/home
zfs create -o mountpoint=/root zroot/data/root
zfs create -o mountpoint=/archive zroot/data/archive
zpool set bootfs=zroot/ROOT/default zroot
zfs list
}
#
# Mount everything
#
function mount_all {
print "Mounting everything"
zfs umount -a
zpool export zroot
zpool import -d /dev/disk/by-partuuid/ -R /mnt zroot -N
zfs mount zroot/ROOT/default
zfs mount -a
mkdir /mnt/boot
mount $boot /mnt/boot
}
#
# Base installation
#
base_pkgs=(
base
$kernel
$kernel-headers
linux-firmware
)
function install_base {
print "Installing Arch Linux"
pacstrap /mnt ${base_pkgs[*]}
genfstab -U -p /mnt >> /mnt/etc/fstab
sed -i 's/^zroot/#zroot/' /mnt/etc/fstab
mkdir /mnt/archive/archzfs
cp /usr/local/bin/* /mnt/archive/archzfs
arch-chroot /mnt /archive/archzfs/chroot_config $mode $disk1 $kernel $timezone $countrycode $country
}
#
# Finish before rebooting
#
function umount_all {
print "Unmounting everything"
umount /mnt/boot
umount -R /mnt
zfs umount -a && zpool export zroot && print "Arch Linux on OpenZFS installation complete"
}
#### ----- MAIN ---- ####
# there are four possible scenarios:
#
# SSD /dev/sd? NVMe /dev/nvme?n1
#
# UEFI <disk1>1 = $boot <disk1>p1 = $boot
# <disk1>2 = $root1 <disk1>p2 = $root1
# <disk2>1 = $spare <disk2>p1 = $spare
# <disk2>2 = $root2 <disk2>p2 = $root2
#
# BIOS <disk1>1 = bios-boot <disk1>p1 = bios-boot
# <disk1>2 = $boot <disk1>p2 = $boot
# <disk1>3 = $root1 <disk1>p3 = $root1
# <disk2>1 = unused <disk2>p1 = unused
# <disk2>2 = $spare <disk2>p2 = $spare
# <disk2>3 = $root2 <disk2>p3 = $root2
#
# $boot is mounted at /boot and used as an efi or grub partition
# $root1 and $root2 form the zpool mirror where the root partition lies
# bios-boot is used by by the system bios to find the grub partition
#
# what to do with $spare ?
#
# validate input with case before proceding
#
case "$mode:$disk1:$disk2" in
bios:/dev/sd?:/dev/sd?)
set_locale
wipe_drives
bios_partitions
boot=${disk1}2
spare=${disk2}2
root1=$(lsblk -dno PARTUUID ${disk1}3)
root2=$(lsblk -dno PARTUUID ${disk2}3) <-- not getting set
create_bios_boot
;;
bios:/dev/nvme?n?:/dev/nvme?n?)
set_locale
wipe_drives
bios_partitions
boot=${disk1}p2
spare=${disk2}p2
root1=$(lsblk -dno PARTUUID ${disk1}p3)
root2=$(lsblk -dno PARTUUID ${disk2}p3) <-- not getting set
create_bios_boot
;;
uefi:/dev/sd?:/dev/sd?)
set_locale
wipe_drives
uefi_partitions
boot=${disk1}1
spare=${disk2}1
root1=$(lsblk -dno PARTUUID ${disk1}2)
root2=$(lsblk -dno PARTUUID ${disk2}2) <-- not getting set
create_uefi_boot
;;
uefi:/dev/nvme?n?:/dev/nvme?n?)
set_locale
wipe_drives
uefi_partitions
boot=${disk1}p1
spare=${disk2}p1
root1=$(lsblk -dno PARTUUID ${disk1}p2)
root2=$(lsblk -dno PARTUUID ${disk2}p2) <-- not getting set
create_uefi_boot
;;
*)
print "usage: archzfs disk1 disk2 mode"
print "disks = '/dev/sd?' | '/dev/nvme?n?'"
print "mode = 'uefi' | 'bios'"
exit
esac
create_pool
create_datasets
mount_all
install_base
umount_all
Here is the second half which runs in the chroot:
chroot_config
#!/usr/bin/env bash
set -e
#
# capture args
#
mode="${1}"
disk1="${2}"
kernel="${3}"
timezone="${4}"
countrycode="${5}"
country="${6}"
#
# local variables
#
# lang=en
user_name=lenny
user_passwd=sysop
root_passwd=sysr00t
case $mode in
uefi)
host_name=archie
;;
bios)
host_name=lurch
;;
esac
#
# OpenZFS packages
#
# zfs-dkms (requires $kernel-headers)
# zfs-linux
# zfs-linux-lts
#
zfs_pkg=zfs-dkms
#
# print messages
#
function print {
echo -e '\n\t\033[0;32m' $1 '\033[0m\n'
}
print "Configuring the new system"
#
# DNS setup
#
# linking stubresolv.conf to resolv.conf does not work in chroot - link on booted system
#
#
# ArchZFS archive permissions
#
chown -R $user_name:users /archive
chmod 700 /archive/archzfs/*
#
# user accounts
#
sed -i '/^PS1=/d' /etc/skel/.bashrc && echo -e "PS1='\u@\h \W \$ '" >> /etc/skel/.bashrc
useradd -m -g users -G wheel -s /bin/bash $user_name
sh -c "echo $user_name:$user_passwd | chpasswd"
sh -c "echo root:$root_passwd | chpasswd"
#
# hostname
#
echo $host_name > /etc/hostname
cat >> /etc/hosts << EOF
#
# localhost config
#
::1 localhost
127.0.0.1 localhost
127.0.1.1 $host_name.localdomain $host_name
EOF
#
# locale
#
# localectl cannot be run in chroot - creating config files manually
sed -i "s/#en_$countrycode.UTF-8/en_$countrycode.UTF-8/" /etc/locale.gen
locale-gen
echo -e "KEYMAP=$country" > /etc/vconsole.conf
echo -e "LANG=en_$countrycode.UTF-8" > /etc/locale.conf
#
# date & time setup
#
# timedatectl cannot be run in chroot - linking to timezone data manually
ln -sf /usr/share/zoneinfo/$timezone /etc/localtime
#
# networking setup
#
network=/etc/systemd/network
#
# ethernet config
#
cat > $network/wired.network << EOF
[Match]
Name=$(networkctl | grep ether | awk '{print $2}')
[Network]
MulticastDNS=yes
DHCP=yes
[DHCP]
RouteMetric=10
UseDomains=yes
EOF
#
# tethering config
#
cat > $network/tethered.network << EOF
[Match]
Name=eth0
[Network]
MulticastDNS=yes
DHCP=yes
[DHCP]
RouteMetric=30
UseDomains=yes
EOF
#
# enable the archzfs repo
#
# NOTE: only enable one server/mirror
#
# Source: https://wiki.archlinux.org/title/unofficial_user_repositories#archzfs
# Origin Server - France
# Server = http://archzfs.com/$repo/x86_64
# Mirror - Germany
# Server = http://mirror.sum7.eu/archlinux/archzfs/$repo/x86_64
# Mirror - Germany
# Server = https://mirror.biocrafting.net/archlinux/archzfs/$repo/x86_64
# Mirror - India
# Server = https://mirror.in.themindsmaze.com/archzfs/$repo/x86_64
# Mirror - US
# Server = https://zxcvfdsa.com/archzfs/$repo/$arch
#
# Key ID: DDF7DB817396A49B2A2723F7403BD972F75D9D76
#
# [archzfs-testing]
# Server = https://archzfs.com/$repo/$arch
# Server = https://zxcvfdsa.com/archzfs/$repo/$arch
#
print "Enabling the archzfs repo"
key_id=DDF7DB817396A49B2A2723F7403BD972F75D9D76
pacman-key --init
pacman-key --populate archlinux
curl -s https://archzfs.com/archzfs.gpg | pacman-key -a -
pacman-key --lsign-key $key_id 2>/dev/null
echo -e "\n[archzfs]\nServer = https://zxcvfdsa.com/archzfs/\$repo/x86_64" >> /etc/pacman.conf
pacman -Syy
#
# utility config
#
utility_pkgs=(
dosfstools
e2fsprogs
exfatprogs
sudo
openssh
irqbalance
vim
usbmuxd
curl
wget
man
reflector
)
print "Installing system utilities"
pacman -S --noconfirm ${utility_pkgs[*]}
sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/" /etc/sudoers
sed -i "s/# Port 22/Port 22/" /etc/ssh/ssh_config
sed -i "s/#Port 22/Port 22/" /etc/ssh/sshd_config
cat > /etc/xdg/reflector/reflector.conf << eof
--country $country
--protocol https
--fastest 6
--sort rate
--save /etc/pacman.d/mirrorlist
eof
systemctl enable sshd
systemctl enable irqbalance
#
# install openzfs
#
print "Installing OpenZFS"
pacman -S --noconfirm $zfs_pkg
zgenhostid=$(hostid)
zpool set cachefile=/etc/zfs/zpool.cache zroot
cp /etc/mkinitcpio.conf /etc/mkinitcpio.conf.bak
sed -i "s/MODULES=()/MODULES=(zfs)/" /etc/mkinitcpio.conf
sed -i "s/BINARIES=()/BINARIES=(fsck)/" /etc/mkinitcpio.conf
sed -i "s/HOOKS=(base udev autodetect modconf block filesystems keyboard fsck)/HOOKS=(base udev autodetect modconf block keyboard zfs filesystems fsck)/" /etc/mkinitcpio.conf
mkinitcpio -p $kernel
#
# systemd and zfs services to be enabled
#
print "Enabling systemd services"
sysd_svcs=(
systemd-networkd
systemd-resolved
systemd-timesyncd
zfs.target
zfs-import-cache
zfs-import.target
zfs-mount
)
for s in ${sysd_svcs[@]}; do
systemctl enable $s
done
#
# determine processor type and install microcode
#
proc_type=$(lscpu | grep 'Vendor ID:' | awk '{print $3}')
case $proc_type in
GenuineIntel)
print "Installing Intel microcode"
pacman -S --noconfirm intel-ucode
proc_ucode=intel-ucode.img
;;
AuthenticAMD)
print "Installing AMD microcode"
pacman -S --noconfirm amd-ucode
proc_ucode=amd-ucode.img
;;
esac
#
# bootloader setup
#
case $mode in
uefi)
print "Configuring systemd-boot"
bootctl install --esp-path=/boot
echo -e "default\tarch\ntimeout\t3" > /boot/loader/loader.conf
arch_conf=/boot/loader/entries/arch.conf
echo -e "title\tArch Linux on OpenZFS\nlinux\tvmlinuz-$kernel" > $arch_conf
echo -e "initrd\t$proc_ucode" >> $arch_conf
echo -e "initrd\tinitramfs-$kernel.img\noptions\tzfs=zroot/ROOT/default rw" >> $arch_conf
bootctl update
bootctl set-default arch.conf
bootctl list
;;
bios)
print "Installing GRUB"
# grub will find the $proc_ucode file
pacman -S --noconfirm grub
grub-install --target=i386-pc $disk1
ZPOOL_VDEV_NAME_PATH=1 grub-mkconfig -o /boot/grub/grub.cfg
;;
esac
"I'm suspicious of people who don't like dogs, but I trust a dog when it doesn't like a person." -- Bill Murray
Offline
This has nothing to do with with the case statement. I suspect it's due to the new partition table not yet being loaded - you can remedy this by running `partprobe` or a similar tool before the lsblk commands. But this is all just speculation as all you know is that *something* failed, but you have so many steps bundled together without any error checking that there's no way to no.
We shouldn't just guess. CHECK the actual output from commands. What is the full lsblk output at the time of failure?
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
This has nothing to do with with the case statement. I suspect it's due to the new partition table not yet being loaded - you can remedy this by running `partprobe` or a similar tool before the lsblk commands. But this is all just speculation as all you know is that *something* failed, but you have so many steps bundled together without any error checking that there's no way to no.
We shouldn't just guess. CHECK the actual output from commands. What is the full lsblk output at the time of failure?
I created this script during an emergency so it was thrown together very quickly. I found out that $root2 was not working correctly when the zpool creation failed. By echoing its value at the time of failure I found out that its was either unset or empty set. It was purely by chance that I added the function to create the boot partition before returning and setting $root1 and $root2 in order to create the zpool. I ran into trouble when I went back and tried to clean up this script and add some basic error handling. As you can surely see I am an amateur when it comes to bash programming.
I think that you are right about the partition table. Maybe I should create a new table on the disks before partitioning them?
"I'm suspicious of people who don't like dogs, but I trust a dog when it doesn't like a person." -- Bill Murray
Offline
I think that you are right about the partition table. Maybe I should create a new table on the disks before partitioning them?
Creating a partition table is part of the partitioning process. While this is should be done, that's not specifically what I was referring to. Rather, even with a new partition table, after you create new partitions, the running kernel can still have 'stale' information about the device partitioning. If it does, when you run any `lsblk` commands you'll get the old information rather than the new/current information.
Some partitioning tools will run the equivalent of `partprobe` when they exit or write the new partitions to disk. I'm not that familiar with sgdisk, though. And as it is being used for indiivdual command sequentially, it may or may not trigger the kernel to update the kernel's information about the partitions.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
lenhuppe wrote:I think that you are right about the partition table. Maybe I should create a new table on the disks before partitioning them?
Creating a partition table is part of the partitioning process. While this is should be done, that's not specifically what I was referring to. Rather, even with a new partition table, after you create new partitions, the running kernel can still have 'stale' information about the device partitioning. If it does, when you run any `lsblk` commands you'll get the old information rather than the new/current information.
Some partitioning tools will run the equivalent of `partprobe` when they exit or write the new partitions to disk. I'm not that familiar with sgdisk, though. And as it is being used for individual command sequentially, it may or may not trigger the kernel to update the kernel's information about the partitions.
What I can tell you about sgdisk is that when it ran there were messages about building a new partition table in memory. Now that I am writing a blank partition table to disk immediately after wiping I no longer see those messages. And by running partprobe per your suggestion the kernel is getting updated immediately after partitioning. Someday when I am not crazy busy with grad school I may try parted to see if it works any better. For now what I have is working and I can rebuild my system in about 20 minutes if I break it. With this script I was able to get my old system with broken efi firmware to boot with grub. Now I have a system I can experiment with and make my script into a proper tool.
Thank you kindly
"I'm suspicious of people who don't like dogs, but I trust a dog when it doesn't like a person." -- Bill Murray
Offline