The diskettes and CD-ROM created so far, do not contain any installation scripts. They are usable as-is if you only need to install your freshly created Linux from Scratch distribution, but for a distribution that must be installed by unexperienced people, installation scripts are essential.
This section gives an overview of a set of example installation scripts. Their functionality is inspired by the Debian installer. These scripts are really simplified and should not be considered suitable for production use. The use of dialog and moderately complex shell programming are central to these installation scripts. All scripts are located in the /usr/scripts directory in the RAM disk and all must have execute permission.
Each invocation of the dialog command represents a visible
screen that is presented to the user. Depending on the command type (e.g. -msgbox or -menu a different type of screen is shown. The output of
most commands (the actual selection) is printed on the standard error device
stderr. The redirect 2>$TEMPNAME
causes this data to be stored in
a temporary file. Using a cat command with back quotes we can put the
contents of that temporary file in a variable. Note that many dialog
commands are extended across multiple lines and the backslash must be the very
last character on a line.
The top level script install_top sets a few variables that will be used
throughout the installation. Next it starts with an introduction screen and it
continues with the menu, which is repeated indefinitely. After each menu
selection, a command is invoked, whose name is the concatenation of install_ and the selection. Therefore we can call eight scripts from the
top level script: install_keyboard, install_partition, install_swap,
install_filesys, install_modules, install_install,
install_configure and install_reboot.
#!/bin/sh # Example top level install script. export TEMPNAME=/tmp/choice export SCRIPTDIR=/usr/scripts export SOURCEDIR=/mnt export TARGETDIR=/target dialog --clear --msgbox \ "Welcome to the Linux Installation Disk\n Press ENTER to start installation.\n Press ALT-F2, ALT-F3 or ALT-F4 for a shell prompt.\n \n Please make sure that all your disks are backed up\n before you start installation" 18 60 while true do dialog --clear --menu "Linux Installation Disk Main Menu" \ 18 60 8 \ keyboard "Select keyboard layout" \ partition "Partition a disk with cfdisk" \ swap "Select a swap partition" \ filesys "Create a file system" \ modules "Load kernel modules" \ install "Install Linux " \ configure "Configure Linux " \ reboot "Reboot the system " 2>$TEMPNAME SELECTION=`cat $TEMPNAME` $SCRIPTDIR/install_$SELECTION done
The script install_keyboard selects one of a few keyboard layouts. The interesting thing is that it also stores the name of the selected map file into the file /tmp/keyfile. Form there, the configuration script can adjust the keyboard layout selection in the target system, so when the target system is rebooted, it will have the correct keyboard layout enabled as well.
#!/bin/sh #Keyboard configuration script. KEYDIR=/usr/share/kbd/keymaps/i386 dialog --clear --menu "Select Keyboard Layout" 18 60 5\ US "Standard US layout (common in the Netherlands)" \ UK "UK layout" \ DE "German layout (QWERTZ)" \ FR "French layout (AZERTY)" \ BE "Belgian layout (AZERTY)" 2>$TEMPNAME SELECTION=`cat $TEMPNAME` case $SELECTION in US ) KEYFILE=$KEYDIR/qwerty/us.map.gz ;; UK ) KEYFILE=$KEYDIR/qwerty/uk.map.gz ;; DE ) KEYFILE=$KEYDIR/qwertz/de.map.gz ;; FR ) KEYFILE=$KEYDIR/azerty/fr.map.gz ;; BE ) KEYFILE=$KEYDIR/azerty/be-latin1.map.gz ;; esac # Save name of keyboard file for later. echo -n $KEYFILE /tmp/keyfile loadkeys $KEYFILE
The script install_partition lets the user select a hard disk and invokes cfdisk.
#!/bin/sh #Partition a hard disk. dialog --clear --menu "Select a hard disk to partition"\ 18 60 6 \ hda "Primary IDE master" \ hdb "Primary IDE slave" \ hdc "Secondary IDE master" \ hdd "Secondary IDE slave" \ sda "First SCSI" \ sdb "Second SCSI" 2>$TEMPNAME SELECTION=`cat $TEMPNAME` cfdisk /dev/$SELECTION
The script install_swap lets the user select a swap partition. It initializes the input field with the string /dev/. Next it asks for confirmation, as mkswap does a really destructive job to the selected partition. It records the partition name in the temporary file /tmp/swappart. The use of an input box to select a partition is not the most user-friendly way to do this job. Ideally the script would read the partition table and put those partitions with type 0x82 in a menu list to select from, but this is more complex.
#!/bin/sh # Select and install a swap partition dialog --inputbox "Enter the name of your swap partition"\ 5 60 /dev/ 2>$TEMPNAME SELECTION=`cat $TEMPNAME` dialog --yesno \ "Any data on $SELECTION will be erased forever!\n Are you really sure you want to continue?" 18 60 if [ $? = 0 ] then echo -n $SELECTION >/tmp/swappart mkswap $SELECTION swapon $SELCTION fi
The script install_filesys is almost a copy of the install_swap script. Apart from the user-friendliness issue, this script should really be extended to allow multiple file system partitions, each on its own mount point.
#!/bin/sh # Select and install a root partition dialog --inputbox "Enter the name of your root partition"\ 5 60 /dev/ 2>$TEMPNAME SELECTION=`cat $TEMPNAME` dialog --yesno \ "Any data on $SELECTION will be erased forever!\n Are you really sure you want to continue?" 18 60 if [ $? = 0 ] then echo -n $SELECTION >/tmp/rootfs mke2fs $SELECTION fi
The script install_modules is not implemented yet. It should offer a way to access the modules.tar.gz file, it should offer a selection of all available modules and next it should selectively extract the selected modules from the tar file. Finally it should ask the user for module parameters and run insmod on the specified module. This is left as an exercise to the reader. Likewise there should be an install_network script to configure the network.
The script install_install lets the user select a CD-ROM drive to install from. In the real world there should be a way to install from other sources as well, such as the network (nfs, wget) or an existing hard disk partition. Next it mounts the CD-ROM on the source directory. Next it asks for the name of the root partition. The script tries to be smart and already suggests the saved partition name in /tmp/rootfs if it exists. It mounts the partition on /target and proceeds to extract the giant tarball distro.tar.gz that contains everything from the distribution.
#!/bin/sh # This installs the Linux system onto the hard disk. dialog --menu "Select CD-ROM to install from" 18 60 6 \ hda "Primary IDE master" \ hdb "Primary IDE slave" \ hdc "Secondary IDE master" \ hdd "Secondary IDE slave" \ sr0 "First SCSI" \ sr1 "Second SCSI" 2>$TEMPNAME SELECTION=`cat $TEMPNAME` mount -r -t iso9660 /dev/$SELECTION $SOURCEDIR if [ $? != 0 ] then dialog --msgbox "Mount failed!" 18 60 exit 1 fi if [ -f /tmp/rootfs ] then ROOTFS=`cat /tmp/rootfs` else ROOTFS=/dev/ fi dialog --inputbox "Select root partition" 18 60\ $ROOTFS 2>$TEMPNAME ROOTFS=`cat $TEMPNAME` echo -n $ROOTFS >/tmp/rootfs mount -t ext2 $ROOTFS $TARGETDIR if [ $? != 0 ] then dialog --msgbox "Mount failed!" 18 60 umount $SOURCEDIR exit 1 fi cd $TARGETDIR tar zxvf $SOURCEDIR/data/distro.tar.gz
The install_reboot script could not be simpler. At least it asks for confirmation.
#!/bin/sh # Reboot script dialog --yesno "Ready to reboot?" 18 60 if [ $? = 0 ] then reboot fi
What remains is the install_configure script. What it does is really dependent on the actual distribution that you installed. As a minimum it should do the following things:
Other things the configuration script could do:
After extracting the base system (the big tarball), you have the following options to proceed:
After the tarball distro.tar.gz is extracted, the root file system contains all files that make up the Linux distribution, including the kernel. A few files (such as /etc/fstab depend on your local situation and should be adjusted by the configuration script. Even then the system is not yet bootable2. Making the system bootable is an essential step that the configuration script must perform.
Assume that the kernel on the hard disk contains all drivers necessary to mount the root file system from the hard disk (all necessary SCSI drivers). If you go for a minimal kernel, you will probably need to create a custom initial RAM disk, one that loads the necessary modules. Some distributions contain the mkinitrd script.
Making the target system bootable consists of the following steps:
In a real-world system the configuration script should accommodate at least three situations:
An alternative to making the system bootable from the hard disk is to create a custom boot diskette. In this case the configuration script only has to dd a pre-existing GRUB image to a formatted diskette and to write a custom menu.lst file to it. This saves the trouble of having to compile a custom uClibc version of GRUB and to keep existing boot managers intact. The problem is that in the near future, most new PCs won't have floppy drives, so this approach cannot be used.
There are at least three ways to debug the installation scripts:
You do not need to recreate the RAM disk image and reboot in order to fix every bug. Instead you can run a shell in a parallel virtual terminal. You can edit the scripts using the vi included in Busybox. You can kill the top level install script to make it start all over. Mount a diskette and (regularly) copy the edited and debugged shell scripts to it. Warning: if you switch off the computer without saving the debugged shell scripts, you lose them of course. Later the debugged scripts can be copied from the diskette back to the $MYBOOT/rootfs/usr/scripts directory on the host system and the boot diskettes or CD-ROM can be rebuilt.