1 TITLE: Boot (not just root) any HD, sample application
3 AUTHOR: Bill Maltby <lfsbill@wlmcs.com>
6 Examples of practical application of the boot_any_hd.txt hint.
10 Version: 0.9 2003-06-14
13 1.0 2003-06-14 - Initial release
15 Unusual for me, I had no urge to explain much of anything in here. I pre-
16 sume that you have read the boot_any_hd.txt hint, if you need to, and any
17 of the other reading material it mentions. I also assume you have *some*
18 level of bash scripting skill above rank novice. If not, beware!
20 I present two processes here. The first is script that can be used as a
21 prototype for backing up your primary drive to a secondary boot drive. The
22 second is a semi-interactive script that will run lilo to install boot
23 blocks supporting the concepts discussed in the boot_any_hd.txt hint.
25 The backup script makes use of a file of sed commands and the lilo script
26 uses a configuration file that provides a little adaptation to your system.
27 A similar file should be done for the backup script, but I haven't done it.
30 I. ROOT TO FALL-BACK ROOT BACKUP SCRIPT
31 II. A GENERALIZED LILO.CONF PROTOTYPE FOR USE BY LBI.SH
32 III. A BOOT-BLOCK INSTALL SCRIPT
35 I. ROOT TO FALL-BACK ROOT BACKUP SCRIPT
36 This script requires that you have bash, find and cpio installed on
39 This script backs up a single root partition, normally /dev/hdb7 for
40 me, to a fall-back root partition on /dev/hdd7, for me. By adjusting
41 these to for your configuration, you should be able to use it. It ex-
42 amines the information from a mount command to generate a script that
43 will do the backup while suppressing copy of directories not contained
44 on your root partition. It also suppresses copy of some files often
45 found in a root FS. By default, the execution of the script made is
46 *not* executed. If you want it to execute automatically just uncom-
47 ment the line near the end of the script.
49 After making your adjustments, you can run it by typing
53 and giving a command line parameter of M, for master or I for incre-
56 If you give it the "M" parameter, it will generate a script to do a
57 full backup and leave a "timestamp" file on the target partition which
58 is used by an incremental backup to check for newer files to copy.
60 If you give it an "I" parameter, it backs up only files with a creation
61 or modification date later than the "time stamp" file.
63 The cpio copy is set to verbose mode and creates a log in /tmp named
64 B7D7{M|I}BU.out. This log can be checked to see if things look good.
65 You may want to remove the "v" parameter to cpio to reduce the amount of
68 A couple of things to watch for: if you intend to be able to boot from
69 the "fall back" drive, remember to adjust various configuration files,
70 like /etc/fstab, that will be sensitive to a (possibly) changed root
71 when you are running from the fall back drive. If you update the orig-
72 inals and back up again, the new ones will overwrite the modified ones
73 unless those files are part of the list of exclusions the script makes.
75 You should change those exclusions to meet your needs.
77 If you do a full backup, it is better to start with an empty fall back
78 file system. Otherwise old stuff may be left in place. If you do a
79 master backup and then only do incrementals, the same problem will tend
80 to occur over time. Every once-in-awhile, empty the fall back partion
81 and do a master backup again.
83 If you are running on the fall back when things like mail happen, and
84 you forgot to put your mail spooling directory someplace *not* on your
85 root partition, you have the possibility that you'll miss some mail
86 when you go back to your normal root because some of the new mail will
87 be on the fall back root.
89 I've not tested with mount --bind stuff.
91 /boot is excluded from the copy. If you change this, there are times
92 you *may* need to run lilo boot blocks install again. Generally it is
93 better to manually copy /boot stuff and remember to run lilo
96 Make sure that permissions prevent running or modification by other
97 users. I keep these components in ~root/bin and have my $PATH set
100 If you use the cron facility to run this automatically in off-hours, it
103 I intentionally use inconsistent script constructs. Sometimes "if, then,
104 else, fi" things and other times "test ... " things. Adapt to suit your-
109 ----------------- CUT ALONG DOTTED LINE ------------------------------------
111 SSD=~/bin # Where sed scripts are.
113 # Exit if they don't give us a run type
114 if [ $# -ne 1 ] ; then
115 echo "Need an I or M parameter for Master or Incremental backup" \
117 echo "Exit 1" >/dev/tty ; exit 1
122 #########################################################################
123 # Make sure I'm rooted on hdb7 or hdd7. CHANGE THIS FOR YOUR CONFIGURATION
124 #########################################################################
126 if [ "x$1" = x/dev/hdb7 ] ; then
128 elif [ "x$1" = x/dev/hdd7 ] ; then
131 echo "*** Error: unexpected root mounted: '$1' on '$2'."
132 echo "*** Error: exiting code 1."
138 M | m ) unset NEWER # This is not really needed, but looks cleaner
141 I | i ) NEWER="-newer /mnt/$MP/BACKUPLAST_$SP"
144 * ) echo "Need I or M parameter: Master/Incremental backup" \
146 echo "Exit 2" >/dev/tty ; exit 2
150 ### After the first time, the mkdir is a waste. ###
151 mkdir -p /mnt/$MP && mount /mnt/$MP
154 if [ $RC -eq 1 ] ; then # mkdir or mount failed
155 echo "*** Error: mkdir or mount /dev/$MP->/mnt/$MP fail: rc=$RC."
156 echo "*** Error: exiting code 2."; exit 2
157 elif [ $RC -ne 0 -a $RC -ne 32 ] ; then
158 echo "*** Error: mkdir or mount bad rc: $RC."
159 echo "*** Error: exiting code 3."; exit 3
162 #########################################################################
163 # The "meat" of the process. Create a script that finds only the root FS
164 # and does either a master backup or an incremental backup. Excludes some
165 # files that normally should *not* be copied.
166 # NOTE: you can use a inline ("here") document to replace the echos. Be sure
167 # you *don't* quote the EOF delimiter - it suppresses variable substitution.
168 #########################################################################
170 echo -e "#!/bin/bash\ncd /"
171 echo "find . \( -name 'mtab' -o -name 'fstab' -o -name '.*.swp' \\"
172 echo "-o -path './mnt/$MP/*' -o -path './boot/*' \\"
173 echo "-o -path './mnt/*' -o -path './tmp/*' \\"
174 echo "-o -path './var/log/*' -o -path './var/run/*' \\"
175 echo "-o -path './var/spool/*' -o -path './var/tmp/*' \\"
177 | sed -f $SSD/B7D7BU.se1
178 echo "\\) -prune -o \\( $NEWER -print \\) \\"
179 echo "| cpio -pdamv /mnt/$MP &> /tmp/B7D7${BUT}BU.out"
180 chmod u+x /tmp/B7D7${BUT}BU.sh
182 echo "touch /mnt/$MP/BACKUPLAST_$SP"
183 } &> /tmp/B7D7${BUT}BU.sh
185 #########################################################################
186 # /tmp/B7D7${BUT}BU.sh # Uncomment to automatically run the script made.
187 #########################################################################
190 ----------------- CUT ALONG DOTTED LINE ------------------------------------
192 Here are the sed commands contained in $SSD/B7D7BU.se1
194 ----------------- CUT ALONG DOTTED LINE ------------------------------------
197 s/^.* on \([^ ][^ ]*\) .*/-o -path '.\1\/*' \\/
198 ----------------- CUT ALONG DOTTED LINE ------------------------------------
200 II. A GENERALIZED LILO.CONF PROTOTYPE FOR USE BY LBI.SH
202 This is a "ptototype" file that can be used by the LBI.sh presented
203 later to automatically "do the right thing" when installing lilo boot
204 blocks for a multi-drive boot configuration. It is expected in to be in
205 /etc/LiloBootInst/lilo.conf-proto. Adjust everything to fit your
208 The directory and this file should be inaccessible to all but the user
209 that will run the script - usually root.
211 ----------------- CUT ALONG DOTTED LINE ------------------------------------
230 menu-title="/dev/hd$BOOTD Drive Boot Menu"
235 default=B7-K6-20030530
237 ###### lfs20030504 BEG ######
240 loader=$TBBOOT/chain.b
246 image=$TBBOOT/K6-20030530
250 append="pci=biosirq idebus=66"
252 image=$TBBOOT/K6-20030530
256 append="pci=biosirq idebus=66"
258 image=$TBBOOT/vmlinuz-2.2.5-15
263 ###### lfs20030504 END ######
264 ----------------- CUT ALONG DOTTED LINE ------------------------------------
266 III. A BOOT-BLOCK INSTALL SCRIPT
268 This has been tested using lilo 22.2 on a "pure" (B)LFS system.
270 In /etc/LiloBootInst/LBI.conf create a file readably only by root with
271 the following contents, adjusted for your configuration.
273 ----------------- CUT ALONG DOTTED LINE ------------------------------------
276 DISKS=(a b d) # CHANGE THIS to show bootable drives
277 WD=$PWD # Where we'll be working
278 HDPFX=/dev/hd # Change for scsi or devfs. Mixed? On your own!
279 BDIR=/boot # Default loc of boot components (non Win*)
280 BOOTB=boot.b # Default prototype boot block(s).
281 CProto=lilo.conf-proto # lilo.conf prototype file
282 CONSOLE=/dev/tty # For fd[0-2] I/O. Devfs? Change as needed.
283 ----------------- CUT ALONG DOTTED LINE ------------------------------------
285 The following shell script, /etc/LiloBootInst/LBI.sh helps get things
286 right during the grind of daily operations. It depends on being able to
287 find the prototype file, detailed above, and the configuration file just
290 To run it, cd to /etc/LiloBootInst and run this command, with the
291 substitutions noted after.
293 ./LBI.sh {-t|-i} -d X -p N [ -D <default-image-label>
295 The "-t" means test only - don't actually install, but do everything
296 else. If you give it "-i", the boot blocks will be installed. The "X"
297 should be replaced with the drive this run is to affect: a for hda, b
298 for hdb, etc. The "N" is replaced by the partition number containing
299 the root file system.
301 If you provide the "-D" and the label of an image, it will be used as
302 the default boot image, overriding any "default=" within the file. If
303 there is no "default=" and no "-D ..." is provided, the system will
304 generate a "-D ..." for you and tell you that it is doing that. This
305 will be the same default as lilo would take.
307 For first runs, be sure to use the "-t" parameter, test. It will process
308 the prototype file and leave the results in a file named *-boot.conf.
309 This is the lilo.conf file that will be referenced by a shell script
310 that is also created, *-boot.sh. You can examine and adjust either of
311 these files as needed.
313 A file, *-boot.out will also be created, using a lilo debug level of v3,
314 showing the information lilo garnered and the decisions made. When this
315 looks good using the "-t" parameter, you can then remove the "-t" and
316 run the *-boot.sh script or rerun LBI.sh and give the "-i" parameter.
318 If you provide the "-i", install parameter, the shell will warn you
319 that you are going to install the boot blocks and ask if you want to do
320 it. Either way, both the "-t" and "-i" leave the *-boot.conf, *-boot.sh
321 and *-boot.out files there for you to examine.
323 The created shell has a "less" at the end that will page through the
324 corresponding *-boot.out file created when the *-boot.sh script is run.
326 The output log has a copy of the lilo command that runs.
328 Here is the shell script.
330 ----------------- CUT ALONG DOTTED LINE ------------------------------------
333 source ./LBI.conf # Load some config/customization vars.
335 #######################################################################
336 # stdusage: issue standard usage message
337 #######################################################################
338 stdusage() { # Standard usage if an error found
339 echo "usage: lilo-boot-install.sh"
340 echo " -{t|i} --> runtype: Test or Install boot blocks"
341 echo " -d [a|b|c|d] --> Drive to *boot*"
342 echo " [-D <def boot>] --> Default boot image lable (optional)"
343 echo " -p partition --> Partition containing ...$BDIR"
344 } &> $CONSOLE <$CONSOLE
346 #######################################################################
347 # stdchecks: see if mount point is involved. Is a boot block found.
348 #######################################################################
349 stdchecks() # Cks common to several drive/part. validations
350 { # $1=mount point preceding some *boot* directory name
351 # $2=some *boot* directory
352 # $3=the drive specified by the -d parameter
353 # $4=the drive partition specified by the -p parameter
354 # $5=a full path name of device that may have a *boot* directory
355 # $6=exit code if there is a failure
357 local BMP=$(mount | grep " on $1$2 " | sed -e 's/ on .*//')
358 if [ -n "$BMP" ] ; then # Found mount point
359 test $BMP != ${HDPFX}$3$4 && {
360 echo "-p $4 doesn't match $BMP on $2. Exit $6 a."
365 test ! -f $1$2/$BOOTB && { # Assure boot blk exists
366 echo "$1$2/$BOOTB not found on $5. Exit $6 b."
372 #######################################################################
373 # getopts process: - validate options and set up parameters
374 #######################################################################
375 RUN=bad # To detect if they don't select test or install
377 # Process all the options passed in - all are required
378 while getopts "tid:p:D:" OPTLTR ; do
380 D ) test -n "$DBL" && { # Default Boot Label seen?
381 echo "Multiple -D given. Default boot label already '$DBL'"
387 # We'll let lilo validate the default boot image and lable
388 # so just leave the case right here.
390 i | t ) # Do install or test?
391 if [ bad = "$RUN" ] ; then # Not seen before?
392 test $OPTLTR = i && unset RUN || RUN=-t
394 echo "-t or -i duplicated or both were given"
399 d ) test -n "$BOOTD" && { # Seen boot dev before?
400 echo "Multiple -d given. Boot drive already '$BOOTD'"
405 for N in ${DISKS[*]} ; do # Drive given is valid?
406 test $N = $OPTARG && { BOOTD=$OPTARG ; break ; }
408 test -z "$BOOTD" && { # Invalid drive given
409 echo "Bad boot drive given '-$OPTLTR $OPTARG'"
415 p ) if BP=`expr "$OPTARG" : '.*[^0-9]'` # Part has non-numeric?
417 echo "Bad partition char at char $BP in '$OPTARG'"
425 * ) eval echo "Bad opt/param \$$((--OPTIND))/\'$OPTARG\' # $OPTIND"
433 #######################################################################
434 # Missing parameters process:, if all needed not found, error out
435 #######################################################################
436 test "$RUN" = bad -o -z "$BOOTD" -o -z "$BOOTP" && {
437 echo -e "Missing a needed parameter: you provided\n \c"
444 #######################################################################
445 # check options vs. available components: set up variables and error
446 # out if discrepancies are detected
447 #######################################################################
448 # See if toboot-boot, partition containing boot-time components, is
449 # available. Later we check to see if it has at least boot.b.
451 sed -n "/hd$BOOTD$BOOTP/s/^\(.*\) on \([^ ][^ ]*\).*$/\1 \2/p")
453 MPT='' ; MDV='' # Mount point/device
454 if [ -n "$TBBOOT" ] ; then # Have something
455 set $TBBOOT ; test / != $2 && MPT=$2 ; MDV=$1
458 if [ "x$MDV" != "x${HDPFX}$BOOTD$BOOTP" ] ; then
459 echo "-p $BOOTP (${HDPFX}$BOOTD${BOOTP}) not mounted. Exit 7."
463 # May have a wrong partition specified for boot-time components. This
464 # might yield an empty mount point when there *is* a mount point that is
465 # on another partition. This would give bad boot-time device. Check for
466 # this condition so we don't get burned.
468 if [ -z "$MPT" ] ; then # No special mount found
469 if [ -d $BDIR ] ; then # But we have a boot dir
470 stdchecks '' $BDIR $BOOTD $BOOTP $MDV 8
471 TBBOOT=${MPT}$BDIR # Set boot-time dir
473 echo "No boot directory found on ${HDPFX}$BOOTD$BOOTP. Exit 8."
476 elif [ "x/$(basename $MPT)" = "x$BDIR" ] ; then # A mounted boot-time pt
477 test -f $MPT/$BOOTB && TBBOOT=$MPT || # Assure boot blk exists
478 { echo "$MPT/$BOOTB not on $MDV. Exit 9." ; exit 9 ; }
479 elif [ -d $MPT$BDIR ] ; then # Boot dir in another FS
480 stdchecks $MPT $BDIR $BOOTD $BOOTP $MDV 10
481 TBBOOT=${MPT}$BDIR # Set boot-time dir
482 elif [ -d "$MPT/liloboot" ] ; then
483 stdchecks $MPT /liloboot $BOOTD $BOOTP $MDV 11
484 TBBOOT=${MPT}/liloboot # Set boot-time dir
486 echo "No boot directory found on ${HDPFX}$BOOTD$BOOTP. Exit 10."
490 #######################################################################
491 # Set up the bios= variables to edit the CProto (lilo.conf-proto) file
492 #######################################################################
494 a ) HDA=0x80;HDB=0x81;HDD=0x82
495 unset MD0 TD0 MD1 TD1
497 b ) HDA=0x81;HDB=0x80;HDD=0x82
498 MD0=0x80 TD0=0x81 MD1=0x81 TD1=0x80
500 d ) HDA=0x81;HDB=0x82;HDD=0x80
501 MD0=0x80 TD0=0x81 MD1=0x81 TD1=0x80
503 * ) echo "Frank Barrone: Holy Crap! How'd we get here Marie? Exit 12"
507 # Eliminate hijacking potential
508 rm -f hd$BOOTD${BOOTP}-boot.sh hd$BOOTD${BOOTP}-boot.out \
509 $WD/hd${BOOTD}$BOOTP-boot.conf
510 PUM=$(umask);umask 077
512 sed -e "s/=.HDA/=$HDA/" -e "s/=.HDB/=$HDB/" -e "s/=.HDD/=$HDD/" \
513 -e "s/\(.\).BOOTD/\1$BOOTD/" \
514 -e "s@=.TBBOOT@=$TBBOOT@" \
515 -e "/map-drive=/s/.MD0/$MD0/" -e "/to=/s/.TD0/$TD0/" \
516 -e "/map-drive=/s/.MD1/$MD1/" -e "/to=/s/.TD1/$TD1/" \
517 -e '/map-drive=$/d' -e '/to=$/d' \
519 > $WD/hd${BOOTD}$BOOTP-boot.conf
521 > hd$BOOTD${BOOTP}-boot.out # Empty log
523 #######################################################################
524 # default image process: -D overrides default= in prototype file. If
525 # no -D given, gets default from prototype file and makes a -D for lilo
526 # so it will be *visible* on $CONSOLE, in the script file and the log.
527 #######################################################################
529 DBL=$(grep default= $WD/hd${BOOTD}$BOOTP-boot.conf \
530 | head -1 | sed 's/.*default=//')
532 DBL=$(grep label= $WD/hd${BOOTD}$BOOTP-boot.conf \
533 | head -1 | sed 's/.*label=//')
535 echo "Note: default boot is $DBL"
536 echo "# default boot is $DBL" >> hd$BOOTD${BOOTP}-boot.out
539 #######################################################################
540 # make lilo script: combine variables and imperatives into shell file
541 # WATCH OUT! Those are *not* leading spaces on the lines between the
542 # "EOD" lines. Those lines use 1 leading tab and then enough spaces to
543 # maintain the visual indent. The "-EOD" removes *only* leading tabs, not
544 # leading spaces. In this case, it doesn't really matter though.
545 #######################################################################
546 cat > hd$BOOTD${BOOTP}-boot.sh <<-EOD
548 lilo $RUN -v3 -b ${HDPFX}$BOOTD \\
549 -m $TBBOOT/hd$BOOTD${BOOTP}map \\
550 -C $WD/hd${BOOTD}$BOOTP-boot.conf \\
552 >> hd$BOOTD${BOOTP}-boot.out 2>&1
553 less hd$BOOTD${BOOTP}-boot.out &> $CONSOLE
557 echo -e "\nInstall script to run is\n"
558 sed -e 's/^/ /' hd$BOOTD${BOOTP}-boot.sh
561 echo "=== INSTALLATION REQUESTED - WILL UPDATE BOOT BLOCKS ==="
562 echo -e "Run it? Y/[N] - \c" ; read A
563 test "x$A" != xY -a "x$A" != xy && {
564 echo "Script available in $WD/hd$BOOTD${BOOTP}-boot.sh"
568 } &> $CONSOLE < $CONSOLE
570 cat hd$BOOTD${BOOTP}-boot.sh >> hd$BOOTD${BOOTP}-boot.out
571 echo "--- ABOVE COMMAND PRODUCED THIS LOG ---" >>hd$BOOTD${BOOTP}-boot.out
573 chmod u+x hd$BOOTD${BOOTP}-boot.sh
574 ./hd$BOOTD${BOOTP}-boot.sh
575 ----------------- CUT ALONG DOTTED LINE ------------------------------------
579 If you post to blfs-support with the subject "boot any hd", I'll keep an
580 eye open and try to help. But I expect you will have read and understood
581 the boot_any_hd.txt hint and the documents it references. I also expect
582 that any scripting problems have been investigated before you post. This
583 si hard enough to debug when its right on my own machines, no telling how
584 hard it would be to help a remote user.