[index]

Mon Jan 23 01:20:22 CET 2006

another step towards livecd

--


I had taken a few days off from this livecd business, quite
nice to think about other things for a change. But today I
decided to roll up my sleeves and get some stuff done.

Last time I looked into it, I had a functioning livecd,
albeit with the teeny weeny problem that it just wouldn't
reboot when told to do so. Instead, init (the main
process started right after the kernel, which is also the last
process to die) hung during the final stages of shutdown.

I realized that this must have something to do with the
fact that the root filesystem is mounted onto another, tiny
filesystem during the bootstrapping processes. Since init was
started by a program residing on this tiny filesystem, what
happens if Gentoo unmounts all temporary filesystems? Im not
sure if thats the problem, but a little googling gave me a
workaround- just copy the shutdown scripts used on a
corresponding livecd- i.e. one which uses the linux-live
scripts.

I had one lying around- slax. So I copied /etc/rc.d/rc.6
over onto my livecd, and modified my /etc/init.d/halt.sh to
just start that script up, and voila! I could shutdown and
reboot the box.

The reason why its so very important that it can reboot is
that the livecd will eventually find its way to a server hall,
and if I want to reboot the box remotely I dont want to have
to take the subway over there and physically reboot it.

Anyway. Now that that problem was out of the world, all I
have left before I have a generic livecd tailor made to suit
my needs was a set of scripts which enable me to store and
restore files to and from the usb stick.

I wrote them today. Here they are:
#!/bin/bash
# initialize.sh
#
# This file will be saved on the usb stick is 
# sourced by the livecd at boot.

# ENVIRONMENT VARIABLES
export USB_ROOT=/mnt/usbdisk
export USB_FUNCTIONS=$USB_ROOT/etc/helmer.func
export USB_SAVES=$USB_ROOT/saved_states

# ACTIONS
mkdir -p $USB_SAVES
#!/bin/bash
# Functions here

# add one or many files to the usb stick.
add_to_usb () {
local ok
total=$(echo $@ | wc -w)
for file in $@ ; do
echo -ne "Saving file '$file' to usb stick...\t"
dir=$(get_abs_dirname $file)
mkdir -p $USB_SAVES/$dir
cp -p $file $USB_SAVES/$dir 2> /dev/null 

if [[ "$?" = "0" ]] ; then
echo "ok."
ok="$ok $file"
else
echo "failed."
failed="$failed $file"
fi
done
ok_num=$(echo $ok | wc -w)
echo "Copied $ok_num of $total to usb stick."
if [[ "$failed" ]] ; then
echo "Failed to copy these files:"
echo $failed | tr " " "\n"
fi

sync
}

# restore all files. um. why dont I use cp -r?
restore_all() {
cd $USB_SAVES
for n in $(find . -type f) ; do
mkdir -p $(dirname /$n)
cp -fp $n /$n
done
cd -
}

# restore a specific file from the usb stick.
restore_from_usb() {
rr_helper $1 restore
}

# remove a file from the usb stick.
remove_from_usb() {
rr_helper $1 remove
}

# helper script for remove and restore
rr_helper () {
inarg=$1
action=$2
cd $USB_SAVES

# check if string matches several files
file=$(find . -type f | grep ${inarg}$)
nr=$(echo $file | wc -w)

case $nr in
0) echo "Cannot find file '$inarg' in savedir. Aborting."
cd -
return 1
;;
1)
if [[ "$action" = "remove" ]] ; then
# If keyword is remove, then delete

rm -f $file
for d in $(find . -depth -type d) ; do
rmdir $d 2> /dev/null
done

sync
elif [[ "$action" = "restore" ]] ; then 
# if keyword is restore, copy the file to root fs.
cp -p $file /${file}
fi
cd -
;;
?)
echo "Found more than one file with the same name. Please be more specific."
echo "Aborting."
cd -
return 1;
esac
}

# helper script, gets file's absolute directory path
get_abs_dirname() {
local file=$1
( cd $(dirname $file) ; pwd )
}
If you see anything which you dont think will work, drop me a line. I havent had a chance to test it yet, I'll do that tomorrow. Oh and to clarify- I'll hardcode the location of initialize.sh onto the cd, and source it at boottime. My intention is that this file will set some variables, then restore all the saved configs on the usb stick to their rightful locations on the root filesystem. Afterwards, the script will start up services like postfix and bind. Right now Im considering making a new runlevel for all the new stuff, and having one script in the default runlevel - the one which loads initialize.sh. Though this is an elegant solution, Im not sure if this will make my life that much easier... The alternative is just not having any main services in any runlevel, and instead start them manually, one at a time, in my script. We'll see. --