|
|
...making Linux just a little more fun! Roll your Desktop into a USB stick/CD
IntroductionHere is a short course (with some excursions) to help you take your existing Desktop, roll it into an ISO pipe and smoke a USB stick or CD. This is not a task for the faint-hearted - there are no automated scripts in here! Part of the reason for this hands-on approach is that each desktop system will have its own quirks, so writing scripts which handle the various conditions which might arise is painful. Secondly, there are numerous choices possible - you must mix your own. Finally, I must confess that I do not feel energetic enough to write the scripts at this point. Instead, you have this article! So if you have spent a lot of time fine-tuning your configuration and want to waste some more time putting it onto a (re)movable drive - read on. Making a read-only root filesystemSince the chosen medium for our ``live'' portable system is a CD or USB stick we do not want to write to it often. In fact, in the case of a CD-R we can only write to it once. It should be obvious, however, that a ``live'' system does need to write something if it is to be counted as among the living! While many mechanisms have been suggested to handle this, we
will (essentially) follow the system chosen by bootcd. To do this,
we need to create a directory The contents of the archive are rather system specific so you will need to choose its contents. However, if you are really, really impatient you can download the listing of the archive that I use and run the following: cd / cat wraith.lst | cpio -o -H crc | gzip -c -9 > /wraith.cpio.gzDid you get a lot of error messages? No? Are you really sure that your system is almost identical to mine? Yes? Then you can skip the next subsection. Choices, choices... How does one find out what files need to be written to on a live system?
One way would be to # Use your real root device in place of /dev/root. last_boot_time=$(dumpe2fs -h /dev/root | \ sed -n -e's/Last mount time: * //p')You may wish to use the log files or the last command instead.
You only need to know the last boot time approximately; subtract a minute
or so from it just to be on the safe side - unless you boot the system
more often than that! Now create a file with that time stamp using the
touch command:
touch -d "$last_boot_time" /tmp/lastbootYou can now create the list of all files that were modified since that last boot (for simplicity we will only bother with the directories /etc and /var; you can add some other directories if
you so desire):
find /etc /var -newer /tmp/lastboot > /tmp/changed # And, just for fun... find /home -newer /tmp/lastboot > /tmp/home_changedHave a look at these lists but don't delete them just yet. You should notice that there are three types of files that are written to on a running system.
/tmp/changed, according to this
classification: /tmp/write will consist of those files (mostly
directories) that are empty at boot time but get written to as the system
runs; /tmp/links will consist of the files that will be
quasi-static - we will keep a static version of these files at boot time
but we might want to change them on a running system. We will include the
third category of files in /tmp/links as well, since we will not
treat them differently - but ultimately you may want to change this.
We first create a directory to hold the files that will be modifiable
at run-time - say In cd / cat /tmp/write | cpio -pdum /wraithWe expect these files to be empty at start-up so we will ``zero'' them. Do this only to the files for which you don't want to keep the contents. For now I assume these are all the files in the list /tmp/write:
for file in $(cat /tmp/write) do if [ -f $file ] then > /wraith/$file fi doneOf course, we also need an empty tmp directory:
mkdir /wraith/tmp chmod 1777 /wraith/tmpNext, we create the links. cd / for i in $(cat /tmp/links) do dir=$(dirname $i) top=$(echo $dir | cut -f2 -d'/') rest=$(echo $dir | cut -f3- -d'/') name=$(basename $i) mkdir -p /wraith/$dir ln -s /wraith/$top.ro/$rest/$name /wraith/$i done # As a safety measure to ensure that all configuration files # have been created mkdir -p /wraith/etc cd /etc for i in * do ln -s /wraith/etc.ro/$i /wraith/etc/$i doneThis is more complicated and needs further explanation. The idea is to make the ``static'' versions of the files available under the .ro
top-level directories. So, for example /wraith/etc/hostname will be
a link to /wraith/etc.ro/hostname.
To see this at work create mount --bind /etc /wraith/etc.ro mount --bind /wraith/etc /etcAfter these mounts, the file /etc/hostname is a link to
the original hostname file which is now available as
/wraith/etc.ro/hostname. Since the left-half of this
link is on the RAM disk we can perform replacement surgery on it:
vi /etc/hostname.new mv /etc/hostname.new /etc/hostnameOn the other hand, if you want to change a file in a sub-directory of /etc, it's a little more complicated:
mkdir /etc/X11.new ln -s /ram/etc.ro/etc/X11/* /etc/X11.new mv /etc/X11.new /etc/X11After this you can edit the files in /etc/X11. Yes, this is quite
twisted but (once you get the hang of it) not difficult to
manage - especially since we expect that we will edit these files
only rarely. An alternate approach is to create the directory tree under
/etc in its entirety only leaving links to the files.
You can use the above mounts to test your choices of
umount /etc umount /wraith/etc.roYou can also remove the .ro directories if you like.
Finally, we create an archive of this directory:
cd /wraith find . -xdev | cpio -o -H crc | gzip -c -9 > /wraith.cpio.gzThe cpio command will tell you how many 512-byte blocks you
wrote. If the archive is really large (more than 1MB or so) then you
probably need to re-do your choices.
Bringing the wraith to life We need a mechanism to bring the # # undead.sh Mount and load up the /wraith directory for use # # Version: 0.3 01-Feb-2005 # # If this has already been run then don't run it again. # We can't handle two wraiths! [ -f /wraith/live ] && exit 0 # Create writable space mount -n -t tmpfs tmpfs /wraith # Create the directory structure cd /wraith gzip -dc /wraith.cpio.gz | cpio -idum cd / # Perform the cross mounts with bind # which is like a directory hard link. cd /wraith for i in * do mkdir $i.ro # We use mount with the -n # To avoid confusing the mtab mount -n --bind /$i /wraith/$i.ro mount -n --bind /wraith/$i /$i done cd / touch /wraith/live : exitFinally, you edit /etc/fstab so that the root filesystem is
mounted read-only at the next boot - just change defaults to
read ro,defaults in the appropriate entry.
Don't stop just yet Reboot and that's it! You have a read-only root system... or
almost. Actually, it is likely that you will find a number of places where
you didn't create the links you need or created the wrong links. Don't
worry. You can modify the cd /wraith find . -xdev | grep -E -v '^./((live)|([^/]*\.ro))' > /tmp/listwill generate the newer list of files. You can unpack the older archive and compare its list of files with /tmp/list.
mkdir /tmp/ghost cd /tmp/ghost zcat /wraith.cpio.gz | cpio -idum find . -xdev > /tmp/oldlist wdiff -a /tmp/list /tmp/oldlistUsing the differences you can see what files you need to create in /tmp/ghost in order to match it up with the running
/wraith. You can save your changes by something like
cd /tmp/ghost find . -xdev | cpio -o -H crc | gzip -c -9 > /tmp/wraith.cpio.gz mv /tmp/wraith.cpio.gz /wraith.cpio.gzThe changes will become automatic at the next boot. Of course, once you write the filesystem to a CD, you will have no chance to revise it again! Undo All this looks too complicated and life is too short? Just remove the
script Making the initrd We want our system to ``run anywhere'' - in particular, we should be
able to mount our root file system whether it resides on a CD or USB
stick (or perhaps even hard disk). If we use a CD then on
most systems this will be on the device What about the remaining 10%? That will take 90% of the work as usual. One possible solution could be to build all the drivers of all possible CD drives, USB readers and the like into the kernel. Unfortunately, automatically probing for some of these devices will occasionally cause other devices to choke-up. It also seems like a bit of a waste to take up such enormous amounts of kernel memory for unused drivers. The solution provided by our intrepid kernel hackers is the modules+initrd mechanism which allows you to write a script that chooses which drivers to load depending on the devices found. The steps The boot loader (see the next section) will load the kernel and the
initrd into memory. We will use a ``standard''
Debian kernel image
which has essentially everything modularized (``essentially'' since we
must have support for at least one file-system built into the kernel
in order to load the init RAM disk - this could change if I understand
After the kernel has done its thing, it sets up the file-system with root
on the initrd and executes
/linuxrc and /sbin/init needed for the initrd. So we
only need to provide the scripts loadmodules and
script.
Driver loadingWriting these scripts was one of the most complex steps for me as it deals with the aspect of Linux that I usually encounter the least - at least on a working system - booting! On the other hand, this is the job for which most installers and other forms of pre-install detection tools have been written. So we follow the ``teacher'' Tom Lehrer's dictum: Plagiarize, Let no one else's work evade your eyes, Remember why the good Lord made your eyes, So don't shade your eyes, But plagiarize, plagiarize, plagiarize... (Only be sure always to call it please, "research".) -- Tom Lehrer, "Lobachevsky" There is a good IDE driver detection routine that is part of the standard
Debian initrd. The Knoppix initrd gives us a safe order in which to load
all the SCSI modules. The Linux-Live initrd has a list of the necessary USB
modules to boot off a stick. So we put all these together to get routines
which I call Still, we should do some work. So (plagiarising from the
hotplug scripts)
I also wrote a procedure Here is the script to loadmodules that resulted from the above deliberations. This scripts depends on a list of modules that are related to block devices. Mounting the root file-system The second script we will use
provides the routine to mount the root device. Again the Using mkinitrd The Debian initrd-tools package is
a collection of scripts and so can be installed on any GNU/linux system
(for example use the source package directly). The main script is
mkinitrd -r "" -k -d /tmp/mkinitrd.confdir -o /dev/nullThis will tell you the name of the working directory which will be something like /tmp/mkinitrd.1234. Now you need to edit the
/tmp/mkinitrd.1234/initrd/linuxrc.conf file to reflect the
various file systems that you may use for your root file system.
Finally, you copy the scripts you created above and generate the
initrd with mkcramfs.
dir=/tmp/mkinitrd.1234 rm $dir/initrd/scripts/* cp allmod.list $dir/initrd/etc cp loadmodules $dir/initrd cp script $dir/initrd chmod +x $dir/initrd/loadmodules chmod +x $dir/initrd/script mkcramfs $dir/initrd initrd.imgIf you build a kernel with ext2 filesystem support instead of
cramfs, then you need to create an ext2 filesystem
image based on the /tmp/mkinitrd.1234 directory instead.
Putting it all togetherWe now combine the ideas of the previous two sections. I assume that you have managed to make your root filesystem boot in a ``read-only'' mode and that you are currently running in that mode. I also assume that you have created an initrd that can boot on ``any'' machine. I know that the latter requirement is hard to check given that you have access to only one machine at a time. Moreover, it is difficult to find friends who will agree if you say ``I have on this floppy an initrd and kernel that I would like to test on your system''; those few will not remain friends if your kernel+initrd manages to fry their system. Selecting the boot loader In order to boot off a CD or USB stick we need some software that can
do that. The nominees are isolinux,
loadlin and grub... and the winner,
in this case, is... The main file for booting using default 0Other than the kernel and the initrd, we need stage2 and
menu.lst in order to complete the list of steps given at the
beginning.
Making the CD First you need a ``pristine'' copy of the root file system.
If you used the mkdir /tmp/pristine mount --bind / /tmp/pristineYou then make a compressed tree of this file system: mkzftree -x /tmp/pristine /hugeroomwhere /hugeroom is some place with a lot of disk space.
Remove the directories /hugeroom/lost+found and
/hugeroom/boot from under this directory. Create an empty
/hugeroom/boot directory to which we copy the kernel image and
initrd. Into the /hugeroom/boot/grub directory goes the file
stage2_eltorito along with menu.lst. These files
will not be compressed.
We now create the CD image: mkisofs -R -J -z -hide-rr-moved -cache-inodes \ -b boot/grub/stage2_eltorito -b boot/boot.cat \ -boot-info-table -boot-load-size 32 \ -no-emul-boot -o mylivecd.iso /hugeroomThen we blank a CD (if necessary) and write our image to it. For a USB stick, we just create a partition and dump the entire image to this partition using dd. Since I do not have a system that can
boot off a USB, I can only check the floppy based boot for such a
system. Perhaps one of the readers can enlighten me on how this is to
be handled for USB-booting BIOSes.
What else? You'll probably want to add a writable Afterword Today one can find a number of GNU/Linux systems that work off Live
CD's. There is Knoppix - and then
there are its Klones.
There is LNX-BBC, tomsrtbt, LTSP and even one called Puppy! There are the CD-based
installers for the common distributions. But, I am still not
satisfied. Each of these make choices that I am not comfortable with. They
choose KDE, Gnome or What's wrong with Sunil's excellent
article then? - just take a minimal Knoppix-like DSL and re-master it.
I would object that Knoppix puts everything in a There are other approaches like that taken by Gibraltar, bootcd or dfsbuild or linux-live. The first two keep the files in a compressed ISO file-system. That makes it usable ``anywhere''. I did try these but for one reason or another they didn't work for me. For example they required the installation of additional packages on my desktop. Ultimately, it comes down to this: I'm a terribly nit-picky kind of person, and I have spent a lot of time fine-tuning my system and no one is allowed to dictate what packages I must install and how they must be configured. [ I like this Kapil guy, and the way he thinks. :) -- Ben ] I enjoy tinkering with such things, and so I must have a system that I understand fully. People also mentioned additional kernel features in late 2.4.x and early 2.6.x that simplify the building of a live CD. Finally, isn't it fun to ``roll your own''?This document was translated from the LaTeX Source by HEVEA.
|
Kapil Hari Paranjape has been a ``hack''-er since his punch-card days.
Specifically, this means that he has never written a ``real'' program.
He has merely tinkered with programs written by others. After playing
with Minix in 1990-91 he thought of writing his first program---a
``genuine'' *nix kernel for the x86 class of machines. Luckily for him a
certain L. Torvalds got there first---thereby saving him the trouble
(once again) of actually writing code. In eternal gratitude he has spent
a lot of time tinkering with and promoting Linux and GNU since those
days---much to the dismay of many around him who think he should
concentrate on mathematical research---which is his paying job. The
interplay between actual running programs, what can be computed in
principle and what can be shown to exist continues to fascinate him.