[TriLUG] Live Linux on USB Flash Drive
Alan Porter
porter at trilug.org
Sat May 17 08:21:06 EDT 2008
I found this script for converting a Ubuntu 7.10 CD to
a bootable USB. I have not dissected it to see how it
works... something I plan to do, since I wrote a similar
utility for Tekelec.
Most of these scripts seem to use SYSLINUX (or ISOLINUX),
a tool that boots off of a CDROM and then loads the kernel
and initramfs into memory and then boots the kernel.
Alan
------------------------
#!/bin/bash
# Convert an Ubuntu live CD iso so that it's bootable off of a USB stick
# Copyright 2007 Red Hat, Inc.
# Jeremy Katz <katzj at redhat.com>
# Jani Monoses <jani at ubuntu.com> (slightly adapted to Ubuntu LiveCD)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
export PATH=/sbin:/usr/sbin:$PATH
usage() {
echo "$0 [--reset-mbr] [--noverify] <isopath> <usbstick device>"
exit 1
}
cleanup() {
[ -d "$CDMNT" ] && umount $CDMNT && rmdir $CDMNT
[ -d "$USBMNT" ] && umount $USBMNT && rmdir $USBMNT
}
exitclean() {
echo "Cleaning up to exit..."
cleanup
exit 1
}
getdisk() {
DEV=$1
p=$(udevinfo -q path -n $DEV)
if [ -e /sys/$p/device ]; then
device=$(basename /sys/$p)
else
device=$(basename $(readlink -f /sys/$p/../))
fi
if [ ! -e /sys/block/$device -o ! -e /dev/$device ]; then
echo "Error finding block device of $DEV. Aborting!"
exitclean
fi
device="/dev/$device"
}
resetMBR() {
getdisk $1
cat /usr/lib/syslinux/mbr.bin > $device
}
checkMBR() {
getdisk $1
bs=$(mktemp /tmp/bs.XXXXXX)
dd if=$device of=$bs bs=512 count=1 2>/dev/null || exit 2
mbrword=$(hexdump -n 2 $bs |head -n 1|awk {'print $2;'})
rm -f $bs
if [ "$mbrword" = "0000" ]; then
echo "MBR appears to be blank."
echo "Do you want to replace the MBR on this device?"
echo "Press Enter to continue or ctrl-c to abort"
read
resetMBR $1
fi
return 0
}
checkPartActive() {
dev=$1
getdisk $dev
# if we're installing to whole-disk and not a partition, then we
# don't need to worry about being active
if [ "$dev" = "$device" ]; then
return
fi
if [ "$(/sbin/fdisk -l $device 2>/dev/null |grep $dev |awk {'print $2;'})" != "*" ]; then
echo "Partition isn't marked bootable!"
echo "You can mark the partition as bootable with "
echo " # /sbin/parted $device"
echo " (parted) toggle N boot"
echo " (parted) quit"
exitclean
fi
}
checkFilesystem() {
dev=$1
USBFS=$(/lib/udev/vol_id -t $dev)
if [ "$USBFS" != "vfat" -a "$USBFS" != "msdos" -a "$USBFS" != "ext2" -a "$USBFS" != "ext3" ]; then
echo "USB filesystem must be vfat or ext[23]"
exitclean
fi
USBLABEL=$(/lib/udev/vol_id -u $dev)
if [ -n "$USBLABEL" ]; then
USBLABEL="UUID=$USBLABEL" ;
else
USBLABEL=$(/lib/udev/vol_id -l $dev)
if [ -n "$USBLABEL" ]; then
USBLABEL="LABEL=$USBLABEL"
else
echo "Need to have a filesystem label or UUID for your USB device"
if [ "$USBFS" = "vfat" -o "$USBFS" = "msdos" ]; then
echo "Label can be set with /sbin/dosfslabel"
elif [ "$USBFS" = "ext2" -o "$USBFS" = "ext3" ]; then
echo "Label can be set with /sbin/e2label"
fi
exitclean
fi
fi
}
checkSyslinuxVersion() {
if [ ! -x /usr/bin/syslinux ]; then
echo "You need to have syslinux installed to run this script"
exit 1
fi
if ! syslinux 2>&1 | grep -qe -d; then
SYSLINUXPATH=""
else
SYSLINUXPATH="syslinux"
#menu texts are trimmed when syslinux is not in / no idea why
SYSLINUXPATH=""
fi
}
if [ $(id -u) != 0 ]; then
echo "You need to be root to run this script"
exit 1
fi
while [ $# -gt 2 ]; do
case $1 in
--noverify)
noverify=1
;;
--reset-mbr|--resetmbr)
resetmbr=1
;;
*)
usage
;;
esac
shift
done
ISO=$1
USBDEV=$2
if [ -z "$ISO" -o ! -e "$ISO" ]; then
usage
fi
if [ -z "$USBDEV" -o ! -b "$USBDEV" ]; then
usage
fi
if [ -z "$noverify" ]; then
# verify the image
echo "Not verifying image...(no checkisomd5 in Ubuntu so skipping)!"
#checkisomd5 --verbose $ISO
if [ $? -ne 0 ]; then
echo "Are you SURE you want to continue?"
echo "Press Enter to continue or ctrl-c to abort"
read
fi
fi
# do some basic sanity checks.
checkSyslinuxVersion
checkFilesystem $USBDEV
checkPartActive $USBDEV
checkMBR $USBDEV
[ -n $resetmbr ] && resetMBR $USBDEV
# FIXME: would be better if we had better mountpoints
CDMNT=$(mktemp -d /media/cdtmp.XXXXXX)
mount -o loop $ISO $CDMNT || exitclean
USBMNT=$(mktemp -d /media/usbdev.XXXXXX)
mount $USBDEV $USBMNT || exitclean
trap exitclean SIGINT SIGTERM
if [ -d $USBMNT/casper ]; then
echo "Already set up as live image. Deleting old in fifteen seconds..."
sleep 15
rm -rf $USBMNT/casper
fi
echo "Copying live image to USB stick"
if [ ! -d $USBMNT/$SYSLINUXPATH ]; then mkdir $USBMNT/$SYSLINUXPATH ; fi
for file in \
README.diskdefines md5sum.txt \
.disk casper pool dists preseed install;do
cp -a $CDMNT/$file $USBMNT/
done
cp $CDMNT/isolinux/* $USBMNT/$SYSLINUXPATH
echo "Installing boot loader"
if [ "$USBFS" = "vfat" -o "$USBFS" = "msdos" ]; then
# syslinux expects the config to be named syslinux.cfg
# and has to run with the file system unmounted
mv $USBMNT/$SYSLINUXPATH/isolinux.cfg $USBMNT/$SYSLINUXPATH/syslinux.cfg
cleanup
if [ -n "$SYSLINUXPATH" ]; then
syslinux -d $SYSLINUXPATH $USBDEV
else
syslinux $USBDEV
fi
elif [ "$USBFS" = "ext2" -o "$USBFS" = "ext3" ]; then
# extlinux expects the config to be named extlinux.conf
# and has to be run with the file system mounted
mv $USBMNT/$SYSLINUXPATH/isolinux.cfg $USBMNT/$SYSLINUXPATH/extlinux.conf
extlinux -i $USBMNT/syslinux
cleanup
fi
echo "USB stick set up as live image!"
------------------------
More information about the TriLUG
mailing list