- Support for alternative distros. I intend to test it with Debian, Porteus and Manjaro.
- Preserve the original script behaviour, for those who are already accustomed to it and so the documentation can remain mostly the same.
- Allow an exported variable for path-to-script to be checked with a conditional and utilised.
- Obviate need for putting /usr/sbin in path.
- Increase the readability and maintainability.
Code: Select all
#!/bin/sh
# Porteus installation script by fanthom
original_author="fanthom"
version_string="v02_20251221"
#maintainer="Porteus Team???"
# Modifications by 555 old-timer -- v002_20251219
# Shellcheck passed = true
# Parts that have been tested and confirmed to be working as expected are marked with a 'TESTED -- Distro' field in their comment.
# =========== Declare variables ==========
# TESTED -- Debian,
# Set working directory, allowing an exported path (if provided) to be picked up and used.
if [ -n "${exported_path+x}" ]; then
work_dir="$exported_path"
else
work_dir="$(pwd)"
fi
path_to_script="$work_dir/.porteus_installer"
#extlinux_conf="$work_dir/syslinux/porteus.cfg"
lilo_menu_path="$work_dir/syslinux/lilo.menu"
debug_file="/tmp/debug.txt"
# Collect first three dev/partition vars with lsblk | AWK
# TESTED -- Debian,
# Where: partition_node, ~filesys and ~mountpoint can be: /dev/sdb1, vfat and /media/$USER/$label respectively, for example.
while read -r a b c; do
partition_node="/dev/$a"
partition_filesys="$b"
partition_mountpoint="$c"
done << EOF
$(lsblk -l -o NAME,FSTYPE,MOUNTPOINTS | awk -v pat="$(dirname "$work_dir")" '$NF==pat {print $1 " " $2 " " $3}')
EOF
# Set last two vars, where: device_node=/dev/sdb and partition_number=1 for example
device_node="$(lsblk -ndo pkname "$partition_node")"
partition_number="$(printf "%s" "$partition_node" | sed "s^/dev/$device_node^^")"
# TESTED x32 & x64 -- Debian,
# Set Porteus target CPU architecture and the appropriate extlinux_version
# TODO Add porteus_cpu_arch to debug file
# As long as this file is included and naming convention remains unchanged,
# then this works and is IMO more reliable than determining arch from booted machine.
# Of course, if fail-proof method is desired, the end-user should be prompted
if grep -q "config" ../porteus/porteus-v*-x86_64.cfg > /dev/null 2>&1; then
porteus_cpu_arch="x64"
elif grep -q "config" ../porteus/porteus-v*-i*86.cfg > /dev/null 2>&1; then
porteus_cpu_arch="x32"
fi
extlinux_version=extlinux."$porteus_cpu_arch"
# =========== Declare functions ==========
# TESTED -- Debian,
check_app_installed () {
if [ ! "$(command -v "$1")" ] && [ ! "$(command -v /usr/sbin/"$1")" ]; then
printf "%s: %s, " "Install" "$1" >> /tmp/.sanity
fi
}
cleanup () {
rm -rf "$path_to_script" > /dev/null 2>&1
}
# 'debug' function: TODO eventually plan to redo
# with printf and rearrange records
debug () {
# TODO Check end-user's distro and add to log
[ "$set_bootloader" ] || set_bootloader=lilo
cat << ENDOFTEXT > "$debug_file"
partition : $partition_node
partition mount point : $partition_mountpoint
installation path : $work_dir
filesystem : $partition_filesys
bootloader : $set_bootloader
error code : $1
system : $(uname -n) $(uname -r) $(uname -m)
mount details : $(grep -w "^$partition_node" /proc/mounts)
full partition scheme :
$(/sbin/sfdisk -l "$device_node" || /usr/sbin/fdisk -l "$device_node")
ENDOFTEXT
[ "$set_bootloader" = lilo ] && [ "$1" ] && cat "$lilo_menu_path" >> "$debug_file"
}
# Exit on non-zero exit code of last command issued
fail_check () {
if [ $? -ne 0 ]; then
printf "%s: %s -- %s\n%s:%s %s: %s\n" "Activation failed with error code" "$1" "Please ask for help" \
"on the Porteus forum" "www.porteus.org/forum" "and provide the information from" "$debug_file"
sleep 1.5; debug "$1"; exit "$1"
fi
}
prompt_user_continue () {
while true; do
printf "%s: " "Continue y/n"
read -r response
case $response in
n|N) printf "%s...\n" "Aborted--exiting"; cleanup; exit 1;;
y|Y) printf "%s...\n" "Continuing"; sleep 1.5; break;;
*) printf "%s" "Invalid response. Press [y] or [n] and [Enter]"
sleep 2; tput cuu 1; tput cub 32; tput ed;;
esac; done
}
# ===== Begin startup 'sanity' checks ====
# Allow only root user:
if [ "$(whoami)" != root ]; then
printf "\n%s\n" "Script requires root privileges" > /tmp/.sanity
fi
# Check if partition properly mounted:
if [ -z "$(printf "%s" "$device_node" | xargs)" ]; then
printf "%s: %s %s\n%s\n" "Current unit" "$partition_mountpoint" "was not mounted correctly." \
"Please unplug and plug it in again or try rebooting your system." >> /tmp/.sanity
fi
# Ensure following utilities are available:
check_app_installed awk; check_app_installed dd; check_app_installed grep
check_app_installed lsblk; check_app_installed sed; check_app_installed sfdisk
# Check for any failure (existence of /tmp/.sanity)
if [ -f /tmp/.sanity ]; then
printf "%s:\n" "Encountered one or more errors. Please correct the following items and try again"
cat /tmp/.sanity; rm /tmp/.sanity;
sleep 1.5; cleanup; exit 1
fi
# =========== Begin operations ===========
# Set traps for signal handling Legend = 1 2 3 15
trap 'printf "%s\n" "Exited prematurely."; cleanup; exit 6' HUP INT QUIT TERM
# Print Porteus wave and intro. Use tput setab 4 if you want only 8 colours
tput bold; tput setaf 7; tput setab 23
printf "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n\n" \
" _.====.._ " \
" ,:._ ~-_ " \
" -Light '\ ~-_ " \
" -Advanced \ \\. " \
" -Modular ,/ ~-_ " \
" -Portable -..__..-'' Porteus ~~--..__\"\" " \
" " \
"==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--" \
"Porteus Activator for BIOS Systems by $original_author -- $version_string "
tput sgr0
printf "%s: %s\n%s\n" "Activating Porteus on" "$partition_node" \
"CAUTION: Ensure this is the correct partition before proceeding."
prompt_user_continue
printf "%s\n" "Flushing filesystem buffers..."; sync
# Write to MBR and set the partition as bootable
if [ "$partition_node" ]; then
dd if="$path_to_script"/mbr.bin of="$device_node" bs=440 count=1 conv=notrunc > /dev/null 2>&1
fail_check 1
sfdisk -A "$device_node" "$partition_number" > /dev/null 2>&1 || /usr/sbin/sfdisk -A "$device_node" "$partition_number" > /dev/null 2>&1
fail_check 2
fi
# Find a suitable boot loader for the partition file system
case "$partition_filesys" in
btrfs|ext[2-4]|fuseblk|msdos|ntfs|vfat)
printf "\n%s\n" "Using extlinux bootloader."
set_bootloader=extlinux
"$path_to_script"/"$extlinux_version" -i "$work_dir"/syslinux > /dev/null 2>&1
fail_check 3
cleanup; printf "%s\n" "Porteus activated successfully. You should safely remove the device and attempt to boot from it."
exit 0;;
exfat) LILO=MBR;;
xfs)
if [ -z "$partition_node" ]; then
printf "%s%s\n" "Can't install LILO on device formatted with XFS filesystem, as it would be destroyed. Please " \
"create a partition on $device_node or re-format it with a different Linux filesystem and try again. Exiting now..."
sleep 1.5; cleanup; exit 1
fi
printf "%s%s%s\n" "By default, LILO is installed to the boot sector of a device's partition i.e. /dev/sdb1. For a " \
"partition with an XFS filesystem, LILO can only be installed to the Master Boot Record of the device. For more info, read: " \
"http://xfs.org/index.php/XFS_FAQ#Q:_Does_LILO_work_with_XFS.3F Consider starting over with a different filesystem, like FAT32."
prompt_user_continue
LILO=MBR;;
*) printf "%s\n" "Unsupported file system--Exiting..."; sleep 1.5; cleanup; exit 1;;
# or should this also set LILO=MBR or allow the rest to continue?...
esac
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# If continuing past this point, install LILO
if [ "$LILO" = MBR ]; then
printf "%s: %s\n" "Installing LILO to the MBR of" "$device_node"
else
printf "%s\n" "Installing LILO bootloader..."
fi
# Create the lilo.menu--redirect the entire stream, using command grouping.
{
if [ "$LILO" = MBR ]; then
printf "%s\n" "boot=$device_node"
else
printf "%s\n" "boot=$partition_node"
fi
printf "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s" \
"prompt" "#timeout=100" "large-memory" "lba32" "compact" "change-rules" "reset" \
"install=menu" "menu-scheme = Wb:Yr:Wb:Wb" "menu-title = \"Porteus Boot-Manager\""
# Keep all but the header (first 8 lines of lilo.conf), Update paths to vmlinuz and initrd
sed -e '1,/#--do-not-delete-me--#/d' -e "s^DO_NOT_CHANGE^$work_dir/syslinux^g" "$work_dir"/syslinux/lilo.conf
} > "$lilo_menu_path"
# Install LILO:
"$path_to_script"/lilo.com -P ignore -C "$lilo_menu_path" -S "$work_dir"/syslinux -m "$work_dir"/syslinux/lilo.map
fail_check 4
# =========== Outro and cleanup ==========
cleanup; printf "%s\n" "Porteus activated successfully. You should safely remove the device and attempt to boot from it."
exit 0





