You install this distribution on a hard disk on a running system, from which you can customize the final CD image.. The gold image file and this script are placed into the dis-tribution
Trang 1■ ■ ■
Linux Gold-System Build
Building a system manually can be fun Building many systems manually is tedious and
prone to error, especially when all systems should be built in exactly the same way For
this reason, Kickstart by Red Hat, Jumpstart by Sun, and other utilities were created to
automate a network-based system build that is based on preset parameters These
utili-ties work well when you are building new systems on a regular basis The downside of this
method is that a client is required to be on the network and it needs to have access to the
server to do a system build Also, a build server needs to be set up and maintained, but if
you are building only a moderate number of systems, it may not be worth the extra effort
to set up a build server
The build script in this chapter has a small image size and can be run from a bootable
CD The CD boots and then automatically calls a script that partitions and formats the
hard disk The script then proceeds to install a preconfigured OS image to the system hard
disk This method has the advantage of having no network or build-server requirements
The newly built system can also have site-specific configurations that may not be part of
a standard installation The script has the added advantage that it can install applications
that may not be in a proprietary format, such as an RPM (Red Hat Package Manager)
The process I used was to find a Linux live distribution on a single boot CD that was
designed to be customizable I chose the “Roll your own Linux Rescue or Setup CD.”1
There are now many distributions like this, including live DVD images for larger
installa-tions, but at the time this one seemed to be the best choice
You install this distribution on a hard disk on a running system, from which you can
customize the final CD image The gold image file and this script are placed into the
dis-tribution directory tree, and the final modification is to change the live CD startup script
to call your build script The last task is to run the script that came with the distribution
to create the final iso file, which you would then burn to a CD The resulting CD
auto-matically boots and runs this install script, prepares the hard drive, and installs the
customized system image I refer to the image as the gold image because it is the master
copy of the system being installed
The process of building a master gold system is basically manual Once the template
sys-tem is built, fully customized, and tuned to your environment, you should create an image
1 http://www.phenix.bnl.gov/~purschke/RescueCD
Trang 2file from that disk The gold system will then mount an NFS server (at /mnt/nfs) with suffi-cient space for the image and run the following command to create the image file
This command creates a compressed tar file of the whole disk on the running gold system It excludes the contents of the /proc and /mnt/nfs directories because they are specific to the gold system, and you can’t use the contents if they are propagated to sub-sequent builds
tar cvfz /mnt/nfs/wholedisk.tar.gz / exclude /proc/* \
exclude /mnt/nfs/*
Most of the build script is for preparing the hard disk to accept the final image created from the gold system The process determines the hard-drive geometry parameters and bases the partitioning on those values, since the disk model and manufacturer are likely
to vary from system to system Once the disk has been prepared, the script creates the file systems and unarchives the gold image
First we assign a bunch of variables that determine and store the architecture parameters
of the hard disk; we will use them to create the input file for sfdisk, which is a Linux parti-tion-table manipulator Additionally, they determine the amount of memory on the system and then use double the memory value for the swap partition It is safe to calculate swap memory as double the amount of base memory The value in /proc/cpuinfo that contains the total amount of memory on a system may vary depending on the live CD image that is being used To deal with this case, the egrep command checks for two of the possible values
If you choose a different live CD, you may want to check that these are valid
#!/bin/sh
bytes_per_cyl=`sfdisk -l /dev/hda | grep Units | awk '{print $5}'`
tracks_per_cyl=`sfdisk -l /dev/hda | grep Disk | awk '{print $5}'`
sectors_per_track=`sfdisk -l /dev/hda | grep Disk | awk '{print $7}'`
sectors_per_cyl=$(($tracks_per_cyl*$sectors_per_track))
bytes_per_sector=$(($bytes_per_cyl/$sectors_per_cyl))
cyl_count=`sfdisk -l /dev/hda | grep Disk | awk '{print $3}'`
usable_cyl=$(($cyl_count-4))
disk_in_sectors=$((($sectors_per_cyl*$usable_cyl)-$sectors_per_track))
mem_in_bytes=`cat /proc/meminfo | egrep "MemTotal:|Mem:" | awk '{print $2}'`
swap_in_bytes=$(($mem_in_bytes*2))
The input file that is sent to sfdisk specifies the size of each partition in sectors The following function (sector_calc) takes its input in bytes and converts the number of bytes into sectors It also determines whether the file system fits evenly on cylinder boundaries
If not, the function rounds up the value to the next cylinder
sector_calc () {
size=$1
slice_in_sectors=$(($size/$bytes_per_sector))
slice_in_cyl=$(($slice_in_sectors/$sectors_per_cyl))
slice_rem=$(($size%$bytes_per_sector))
if [ $slice_rem -ne 0 ]
Trang 3then
slice_in_cyl=$(($slice_in_cyl+1))
slice_in_sectors=$((($slice_in_cyl*$sectors_per_cyl)-$sectors_per_track))
else
slice_in_sectors=$((($slice_in_cyl*$sectors_per_cyl)-$sectors_per_track))
fi
}
Now the script determines the size in sectors for each of the file systems that will be on
the final build by sending the file-system size values to the sector_calc function
sector_calc $swap_in_bytes
swap_in_sectors=$slice_in_sectors
sector_calc 250000000
root_in_sectors=$slice_in_sectors
sector_calc 30000000
boot_in_sectors=$slice_in_sectors
sector_calc 1000000000
var_in_sectors=$slice_in_sectors
sector_calc 512000000
home_in_sectors=$slice_in_sectors
sector_calc 512000000
tmp_in_sectors=$slice_in_sectors
A lot of file systems were part of this build, but it would be trivial to modify the code to
remove unnecessary ones or to add your own file systems to match your gold build
The last two file systems split in half whatever is left over after the other file systems are
allocated This was done in my environment because we used these two partitions more
heavily than the rest and wanted to distribute the remainder of the space evenly Their
sector calculations are slightly different because they are based on the size of the whole
disk minus the other file systems
rest_of_disk_in_sectors=$(($disk_in_sectors-$swap_in_sectors-\
$boot_in_sectors-$root_in_sectors-$var_in_sectors-$home_in_sectors-\
$tmp_in_sectors))
usr_in_sectors=$(($rest_of_disk_in_sectors/2/$sectors_per_cyl*\
$sectors_per_cyl))
usrlocal_in_sectors=$usr_in_sectors
We need to define and write the partition-table file that will be used to format the
new system’s hard disk We begin by reproducing the partitioning output from sfdisk
-d /dev/hda That command dumps the partition table in a format that can be used as
input to subsequently partition another disk You would want to do this on your gold
Trang 4system to make sure the script output and the gold partition table match while account-ing for any hard drive–architecture variations
PARTTAB=/tmp/parts.out
double_sectors_per_track=$((2*$sectors_per_track))
cat > $PARTTAB <<SOMETAG
# partition table of /dev/hda
unit: sectors
The interesting scripting technique here is the use of the cat command to enter text in
a free format Here cat takes input from the code up to the tag SOMETAG and then redirects that output to the output file specified by $PARTTAB This code structure is called a here-document A here-document is where free-format text, opened and closed by a delimiter (SOMETAG) in this case, is used as input to another code structure, such as a loop or, in this case, a variable The previous version of this code had each of the lines of text individually redirected to the output file This technique makes the code less cluttered and easier to read; you can find more details about this in Chapter 28
This code may be somewhat daunting to read and comprehend because of the format-ting and the length of each line With a bit of close examination, however, you’ll see it isn’t quite as complex as it might seem
/dev/hda1 :\
start=$sectors_per_track,size=$boot_in_sectors,Id=83,bootable
/dev/hda2 : start=$(($sectors_per_track+$boot_in_sectors)),size=$\
(($disk_in_sectors-$boot_in_sectors)),Id=5
/dev/hda3 : start=0,size=0,Id=0
/dev/hda4 : start=0,size=0,Id=0
/dev/hda5 : start=$(($double_sectors_per_track+$boot_in_sectors)),\
size=$usr_in_sectors,Id=83
/dev/hda6 : start=$\
(($double_sectors_per_track+$boot_in_sectors+$usr_in_sectors)),\
size=$usrlocal_in_sectors,Id=83
/dev/hda7 : start=$\
(($double_sectors_per_track+$boot_in_sectors+\
$usr_in_sectors+$usrlocal_in_sectors)),size=$var_in_sectors,Id=83
/dev/hda8 : start=$\
(($double_sectors_per_track+$boot_in_sectors+\
$usr_in_sectors+$usrlocal_in_sectors+$var_in_sectors)),\
size=$home_in_sectors,Id=83
/dev/hda9 : start=$\
(($double_sectors_per_track+$boot_in_sectors+\
$usr_in_sectors+$usrlocal_in_sectors+$var_in_sectors+\
$home_in_sectors)),size=$tmp_in_sectors,Id=83
/dev/hda10 : start=$\
(($double_sectors_per_track+$boot_in_sectors+\
Trang 5$home_in_sectors+$tmp_in_sectors)),size=$swap_in_sectors,Id=82
/dev/hda11 : start=$\
(($double_sectors_per_track+$boot_in_sectors+\
$usr_in_sectors+$usrlocal_in_sectors+$var_in_sectors+\
$home_in_sectors+$tmp_in_sectors+$swap_in_sectors)),\
size=$root_in_sectors,Id=83
SOMETAG
Each line is simply a partition definition They are all part of the cat output that is being
written to the file that will build the file-system structure on the hard disk Each line is of
the following form:
/dev/partition : start={start sector},size={sectors},Id={partition type},[bootable]
The start (start=) and size (size=) calculations are very long and may get a little
confus-ing If you read these lines in order starting at /dev/hda5, you’ll see that the calculation just
increments the start position of the file system by the size of the previous file system
Finally you are able to install the newly created partition table to the disk
sfdisk -f /dev/hda < $PARTTAB
Now you can create all ext2 file systems on disk Of course, you may want to use other
file-system types
for slice in 1 5 6 7 8 9 11
do
echo Making file system on slice $slice
mke2fs /dev/hda$slice
done
We create a mount point in /tmp for accessing the hard drive and mount the root
parti-tion to it Note that when this script is running, the /tmp directory is part of a ramdisk from
the live CD Once the root partition has been mounted, the script creates all other drive
mount points on the physical disk
mkdir -p /tmp/root
mount /dev/hda11 /tmp/root
for dir in boot usr var home tmp
do
mkdir -p /tmp/root/$dir
done
Since there is some dependency between the file systems, the mounting process needs
to happen in the proper order: the lowest-level partitions should be mounted first
mount /dev/hda1 /tmp/root/boot
mount /dev/hda5 /tmp/root/usr
if [ ! -d /tmp/root/usr/local ]
Trang 6mkdir /tmp/root/usr/local
fi
mount /dev/hda6 /tmp/root/usr/local
mount /dev/hda7 /tmp/root/var
mount /dev/hda8 /tmp/root/home
mount /dev/hda9 /tmp/root/tmp
Here is where the prepared disk is populated We unarchive the whole disk-image file onto the newly formatted hard drive All the files should land in the correct file system, since the file system has been partitioned in exactly the same way as the original gold system
cd /tmp/root
tar xvfzp /usr/wholedisk.tar.gz
cd /
Once that is complete, you need to create the swap partition and install the boot loader The chroot command runs the lilo boot loader installation based on the hard drive /root directory, and not from the root of the CD Of course, if you choose to use grub instead of lilo, you’ll need to modify this command
mkswap /dev/hda10
chroot /tmp/root lilo -C /etc/lilo.conf
We have reached the end of the installation process The script dismounts all partitions
in the proper order Partition 6 should be dismounted first since /usr/local is attached to /usr, and partition 11 should be dismounted last since it is /root Now when the newly built system is rebooted, it should be an exact duplicate of your original gold system except for any hard-drive size differences All that is left to do is to make system-specific changes, such as entering your IP address and a system name, and then you can connect the finished system to the network
for slice in 6 1 5 7 8 9 11
do
umount /dev/hda$slice
done