You are not logged in.

#1 2021-05-14 01:00:55

lenhuppe
Member
From: New Hampshire
Registered: 2018-12-10
Posts: 86
Website

SOLVED Strange issue with case statement

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)

Offline

#2 2021-05-14 04:49:10

ayekat
Member
Registered: 2011-01-17
Posts: 1,452
Website

Re: SOLVED Strange issue with case statement

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
	}

{,META,RE}PKGBUILDSpacman-hacks (includes makemetapkg and remakepkg) │ dotfiles

Offline

#3 2021-05-14 14:00:19

lenhuppe
Member
From: New Hampshire
Registered: 2018-12-10
Posts: 86
Website

Re: SOLVED Strange issue with case statement

ayekat wrote:

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
	}

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

Offline

#4 2021-05-14 14:13:32

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 25,280

Re: SOLVED Strange issue with case statement

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

#5 2021-05-14 14:34:12

lenhuppe
Member
From: New Hampshire
Registered: 2018-12-10
Posts: 86
Website

Re: SOLVED Strange issue with case statement

Trilby wrote:

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?

Offline

#6 2021-05-14 16:52:01

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 25,280

Re: SOLVED Strange issue with case statement

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 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

#7 2021-05-14 21:24:59

lenhuppe
Member
From: New Hampshire
Registered: 2018-12-10
Posts: 86
Website

Re: SOLVED Strange issue with case statement

Trilby wrote:
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

Offline

Board footer

Powered by FluxBB