#!/bin/bash # ############################################################### # # Installes the LiveCD on local hard disk # # Boot LiveCD and run this script as root # # Urs Beyerle # ############################################################### ############################################################### # Definitions ############################################################### # set PATH PATH="/usr/bin:/usr/sbin:/bin:/sbin:/usr/X11R6/bin" # RPMs that are no longer needed and may break future udpates RPMS_TO_REMOVE="kernel-module-squashfs \ kernel-module-unionfs \ kernel-module-aufs \ unionfs-.* \ aufs-.* \ squashfs-.*" # RPMs that can break future Scientific Linux updates # because there are not part of Scientific Linux RPMS_TO_REMOVE_SL="" # RPMs that can break future PSI SL updates # because there are not part of PSI Scientific Linux RPMS_TO_REMOVE_PSI="" # files which should be restored from .ori files FILES_RESTORE="/etc/init.d/netfs \ /etc/init.d/autofs \ /etc/init.d/halt \ /etc/init.d/network /etc/init.d/functions \ /etc/rc.d/rc.sysinit \ /etc/sysconfig/afs \ /etc/motd \ /etc/redhat-release \ /etc/rc.d/rc.local" # LiveCD init scripts will be removed LIVECD_INIT_SCRIPTS="runfirst \ runveryfirst \ runlast \ kudzu-auto \ login" # Main directories which should be not be copied DIR_NOT_COPY="/proc \ /dev \ /livecd \ /boot \ /afs \ /sys \ /media \ /misc \ /mnt \ /net \ /initrd" # Mount point of the new SL system NEW=/mnt/harddisk # Name of the script SCRIPTNAME=$( basename $0 ) # dir of mounted /$MOUNTDIR/live MOUNTDIR=livecd ############################################################### # Functions ############################################################### function usage() { ## Usage # ---------------------------------------------------------- cat <<EOF $SCRIPTNAME [OPTIONS] -mbr=[DEVICE] [PARTITION] Installes LiveCD on PARTITION and the bootloader grub into the Master Boot Record (MBR) of DEVICE. The MBR will be backed up to PARTITION. OPTIONS: -h --help : Print this screen -swap=[partition] : Use [partition] as swap -win=[partition] : Your active Windows partition. If not given, $SCRIPTNAME tries to find it -nogrub : Do not install grub. You have to install manually a bootloader (not recommended) -floppy : Needed, if grub should be installed on floppy In this case use -mbr=/dev/fd0 -floppy -norpmremove : Do not remove RPMs that can break future updates (not recommended) -y : Answer all questions with yes Example: $SCRIPTNAME -swap=/dev/sda3 -mbr=/dev/sda /dev/sda2 Will install LiveCD on /dev/sda2 (= second partition on first SATA disk). All data on /dev/sda2 will be deleted. /dev/sda3 has to be a Linux Swap partion. GRUB will be installed in the MBR of /dev/sda (= first SATA disk). Remarks: To display your hard disk partitions, user 'fdisk -l'. Use fdisk, qtparted or parted to create an empty Linux partition. EOF } function exit_now() { local exitcode=$1 umount $INSTALL_PART 2>/dev/null exit $exitcode } ############################################################### # Main ############################################################### ### are we root? ### ----------------------------------------------------------- if [ "$( whoami )" != "root" ]; then echo; echo "Please run this script as root: 'su - -c $SCRIPTNAME'"; echo exit_now 1 fi ### read options from command-line ### ----------------------------------------------------------- while [ $# -gt 0 ]; do case "$1" in -h) usage; exit_now;; --help) usage; exit_now;; -swap*) if echo $1 | grep -q '=' ; then SWAP_PART=$( echo $1 | sed 's/^-swap=//' ) else shift SWAP_PART=$1 fi ;; -mbr*) if echo $1 | grep -q '=' ; then MBR_DEV=$( echo $1 | sed 's/^-mbr=//' ) else shift MBR_DEV=$1 fi ;; -win*) if echo $1 | grep -q '=' ; then WIN_PART=$( echo $1 | sed 's/^-win=//' ) else shift WIN_PART=$1 fi ;; -nogrub) NOGRUB=$1;; -norpmremove) NORPMREMOVE=$1;; -floppy) FLOPPY=$1;; -y) YES=$1;; *) INSTALL_PART=$1;; esac shift done echo ### display fdisk -l ### ----------------------------------------------------------- echo "Output of 'fdisk -l' ..." fdisk -l echo ### test if $INSTALL_PART is defined ### ----------------------------------------------------------- if [ ! $INSTALL_PART ]; then echo "No partition defined for installation." echo "Please see '$SCRIPTNAME -h'."; echo exit_now 1 fi ### test if MBR_DEV is given ### ----------------------------------------------------------- if [ ! $NOGRUB ]; then if [ ! $MBR_DEV ]; then echo "No MBR device defined." echo "Please see '$SCRIPTNAME -h'." echo exit_now 1 fi fi ### test if $INSTALL_PART exists ### ----------------------------------------------------------- fdisk -l | cut -d" " -f1 | grep -q "^${INSTALL_PART}$" if [ "$?" != "0" ]; then echo "Partition $INSTALL_PART not found! See 'fdisk -l'." echo "Or you have to reboot first to make the partition table active." echo exit_now 1 fi ### test if $INSTALL_PART is a Linux partition ### ----------------------------------------------------------- fdisk -l | grep "Linux$" | cut -d" " -f1 | grep -q "^${INSTALL_PART}$" if [ "$?" != "0" ]; then echo "Partition $INSTALL_PART is not a Linux partition! (see 'fdisk -l')." echo "Use fdisk and/or qtparted to create a Linux partition!" echo "You have to reboot first to make the partition table active." echo exit_now 1 fi ### test if $SWAP_PART exists and is a Linux Swap partition ### ----------------------------------------------------------- if [ $SWAP_PART ]; then fdisk -l | cut -d" " -f1 | grep -q "^${SWAP_PART}$" if [ "$?" != "0" ]; then echo "Swap partition $SWAP_PART not found! (see 'fdisk -l')." echo "Or you have to reboot first to make the partition table active." echo exit_now 1 fi fdisk -l | grep "Linux swap" | cut -d" " -f1 | grep -q "^${SWAP_PART}$" if [ "$?" != "0" ]; then echo "Partition $SWAP_PART is not a Linux swap partition! (see 'fdisk -l')." echo "Use fdisk and/or qtparted to create a Linux Swap partition !" echo "You have to reboot first to make the partition table active." echo exit_now 1 fi fi ### set $INSTALL_DEV (eg. /dev/sda) ### ----------------------------------------------------------- INSTALL_DEV=$( echo "$INSTALL_PART" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' ) INSTALL_PART_NR=$( echo "$INSTALL_PART" | sed -e 's%.*/[sh]d[a-z]\([0-9]*\)$%\1%' ) ### print warning ### ----------------------------------------------------------- echo "------------------------------------------------------------" echo " LiveCD will be installed on partition $INSTALL_PART" [ "$SWAP_PART" ] && echo " Partition $SWAP_PART will be used as swap partition." [ ! $NOGRUB ] && echo " GRUB will be installed in Master Boot Record of $MBR_DEV" echo " !! All data on $INSTALL_PART will be lost !!" echo "------------------------------------------------------------" echo ### continue? ### ----------------------------------------------------------- if [ ! $YES ]; then echo -n "Continue (y/N)? " read key echo [ "$key" != "y" ] && exit_now 0 fi ### format $SWAP_PART (don't format swap, if already formated) ### ----------------------------------------------------------- if [ $SWAP_PART ]; then echo "Make swap on $SWAP_PART ..." swapoff -a >/dev/null 2>&1 swapon $SWAP_PART 2>/dev/null if [ "$?" != "0" ]; then echo "Format $SWAP_PART as swap." mkswap $SWAP_PART fi echo fi ### format $INSTALL_PART ### ----------------------------------------------------------- echo -n "Format $INSTALL_PART, please wait ... " mkfs.ext3 -q $INSTALL_PART || exit_now 1 echo "done."; echo ### mount $INSTALL_PART ### ----------------------------------------------------------- echo -n "Try to mount $INSTALL_PART to $NEW ... " mkdir -p $NEW mount $INSTALL_PART $NEW || exit_now 1 echo "done."; echo ### copy root dirs ### ----------------------------------------------------------- echo "Copy Live System to $INSTALL_PART ..." root_dirs=$( ls / ) for dir in $root_dirs; do # check if dir is not in $DIR_NOT_COPY do_not_copy="" for not_dir in $DIR_NOT_COPY; do if [ "$not_dir" = "/$dir" ]; then do_not_copy="yes" break fi done # do not copy links [ -L /$dir ] && do_not_copy="yes" fail="" if [ ! $do_not_copy ]; then echo -n " * Copy /$dir ... " cp -a /$dir $NEW || fail=true echo "done." fi done echo if [ $fail ]; then echo "ERROR: Not everything was copied to $INSTALL_PART" exit_now 1 fi ### move /usr/opt back to /opt ### ----------------------------------------------------------- if [ -d $NEW/usr/opt ]; then echo -n "Move /opt back ... " mv $NEW/usr/opt $NEW/ echo "done."; echo fi ### create dirs which were not copied ### ----------------------------------------------------------- for dir in $DIR_NOT_COPY; do mkdir $NEW/$dir done # we do not need this directories rmdir $NEW/livecd # if not yet existing, create mkdir -p $NEW/srv mkdir -p $NEW/selinux ### copy back original files ### ----------------------------------------------------------- echo -n "Restore original files ... " for file in $FILES_RESTORE; do [ -r $NEW/${file}.ori ] && mv -f $NEW/${file}.ori $NEW/${file} done echo "done."; echo ### define kernel version ### ----------------------------------------------------------- rpm --quiet -q kernel && UP_installed=true rpm --quiet -q kernel-smp && SMP_installed=true [ $UP_installed ] && KERNEL_VERSION=$( rpm -q --qf "%{V}-%{R}" kernel 2>/dev/null ) [ $SMP_installed ] && KERNEL_VERSION=$( rpm -q --qf "%{V}-%{R}" kernel-smp 2>/dev/null ) if [ ! $KERNEL_VERSION ]; then echo "ERROR: Kernel version could not be determined - installation failed"; echo exit_now 1 fi if [ ! $NOGRUB ]; then ### Backup Master Boot Record MBR ### ----------------------------------------------------------- if [ ! $NOGRUB ]; then # do we have already a backup? MBR_FILENAME="MBR$( echo $MBR_DEV | tr / _ ).bak" if [ ! -e /tmp/$MBR_FILENAME ]; then echo "Backup Master Boot Record (MBR) of $MBR_DEV ..." dd if=$MBR_DEV of=/tmp/$MBR_FILENAME bs=512 count=1 fi cp -a /tmp/$MBR_FILENAME $NEW/$MBR_FILENAME echo "MBR saved as $MBR_FILENAME on $INSTALL_PART and on /tmp" echo fi ### install grub ### ----------------------------------------------------------- echo "Run grub-install ... " mkdir -p $NEW/boot/grub if [ $FLOPPY ]; then grub-install --root-directory=$NEW $MBR_DEV else grub-install --no-floppy --root-directory=$NEW $MBR_DEV fi echo "done."; echo ### check for device.map file ### ----------------------------------------------------------- DEVICE_MAP=$NEW/boot/grub/device.map if [ ! -e $NEW/boot/grub/device.map ]; then echo "ERROR: $NEW/boot/grub/device.map not found" exit_now 1 fi ### convert dev syntax to grub syntax ### ----------------------------------------------------------- GRUB_INSTALL_DEV=$( grep $INSTALL_DEV $DEVICE_MAP | awk '{ print $1 }' ) GRUB_ROOT_PART=$( echo "$GRUB_INSTALL_DEV" | sed "s%)$%,`expr $INSTALL_PART_NR - 1`)%" ) ### find active Windows partition ### ----------------------------------------------------------- if [ ! $WIN_PART ]; then # try to find active Windows partition WIN_PART=$( fdisk -l 2>/dev/null | awk '{ if ($2 == "*" && $7 ~ "NTFS") print $1 }' | head -1 ) fi if [ $WIN_PART ]; then WIN_installed=true WIN_DISK=$( echo "$WIN_PART" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' ) WIN_PART_NR=$( echo "$WIN_PART" | sed -e 's%.*/[sh]d[a-z]\([0-9]*\)$%\1%' ) # convert dev syntax to grub syntax GRUB_WIN_DEV=$( grep $WIN_DISK $DEVICE_MAP | awk '{ print $1 }' ) GRUB_WIN_PART=$( echo "$GRUB_WIN_DEV" | sed "s%)$%,`expr $WIN_PART_NR - 1`)%" ) # $GRUB_WIN_PART should be something like (hd0,0) echo "Found active Windows partition ( $WIN_PART = $GRUB_WIN_PART )" echo "Will add entry for Windows in GRUB." echo fi ### create grub.conf file ### ----------------------------------------------------------- echo "Create grub.conf ..." TITLE="Linux" [ -e $NEW/etc/redhat-release ] && TITLE=$( cat $NEW/etc/redhat-release ) DEFAULT=0 # set default=1, if smp kernel is running uname -r | grep -q smp [ "$?" = "0" ] && DEFAULT=1 cat > $NEW/boot/grub/grub.conf <<EOF # grub.conf generated by $SCRIPTNAME default=$DEFAULT timeout=5 splashimage=$GRUB_ROOT_PART/boot/grub/splash.xpm.gz #hiddenmenu EOF if [ $UP_installed ]; then echo "Add entry for UP kernel into grub.conf" cat >> $NEW/boot/grub/grub.conf <<EOF title $TITLE (${KERNEL_VERSION}) root $GRUB_ROOT_PART kernel /boot/vmlinuz-$KERNEL_VERSION ro root=$INSTALL_PART initrd /boot/initrd-$KERNEL_VERSION.img EOF fi if [ $SMP_installed ]; then echo "Add entry for SMP kernel into grub.conf" cat >> $NEW/boot/grub/grub.conf <<EOF title $TITLE (${KERNEL_VERSION}smp) root $GRUB_ROOT_PART kernel /boot/vmlinuz-${KERNEL_VERSION}smp ro root=$INSTALL_PART initrd /boot/initrd-${KERNEL_VERSION}smp.img EOF fi if [ $WIN_installed ]; then echo "Add entry for Windows into grub.conf" cat >> $NEW/boot/grub/grub.conf <<EOF title Windows rootnoverify $GRUB_WIN_PART chainloader +1 EOF fi chmod 600 $NEW/boot/grub/grub.conf ln -s ../boot/grub/grub.conf $NEW/etc/grub.conf ln -s ./grub.conf $NEW/boot/grub/menu.lst echo "done."; echo ### create /etc/sysconfig/grub file ### ----------------------------------------------------------- cat > $NEW/etc/sysconfig/grub <<EOF boot=$MBR_DEV forcelba=0 EOF fi ### install kernel and other files into /boot ### ----------------------------------------------------------- echo "Install kernel(s) ..." [ -e /boot/vmlinuz ] && BOOT_DIR=/boot [ -e /boot/boot/vmlinuz ] && BOOT_DIR=/boot/boot if [ ! $BOOT_DIR ]; then echo "ERROR: No kernel found - installation failed"; echo exit_now 1 fi cp -a $BOOT_DIR/vmlinuz $NEW/boot/vmlinuz-${KERNEL_VERSION} cp -a $BOOT_DIR/vmlinuzs $NEW/boot/vmlinuz-${KERNEL_VERSION}smp 2>/dev/null cp -a $BOOT_DIR/System.map-* $NEW/boot/ cp -a $BOOT_DIR/config-* $NEW/boot/ cp -a $BOOT_DIR/symvers-*.gz $NEW/boot/ 2>/dev/null cp -a $BOOT_DIR/grub/splash.xpm.gz $NEW/boot/grub/ 2>/dev/null cp -a $BOOT_DIR/message.ja $NEW/boot/ 2>/dev/null cp -a $BOOT_DIR/message $NEW/boot/ 2>/dev/null echo "done."; echo ### create /etc/sysconfig/kernel file ### ----------------------------------------------------------- cat > $NEW/etc/sysconfig/kernel <<EOF # UPDATEDEFAULT specifies if new-kernel-pkg should make # new kernels the default UPDATEDEFAULT=yes # DEFAULTKERNEL specifies the default kernel package type DEFAULTKERNEL=kernel EOF ### create /etc/fstab ### ----------------------------------------------------------- cat > $NEW/etc/fstab <<EOF $INSTALL_PART / ext3 defaults 1 1 devpts /dev/pts devpts gid=5,mode=620 0 0 tmpfs /dev/shm tmpfs defaults 0 0 proc /proc proc defaults 0 0 sysfs /sys sysfs defaults 0 0 EOF if [ $SWAP_PART ]; then echo "$SWAP_PART swap swap defaults 0 0" >> $NEW/etc/fstab fi ### make initrd ### (needs $NEW/etc/fstab to find correct modules for root filesystem !!) ### ----------------------------------------------------------- echo "Create initrd(s) ..." # initrd should not be build on tmpfs (we take $NEW/tmp instead of /tmp) sed -i "s|^TMPDIR=.*|TMPDIR=\"$NEW/tmp\"|" /usr/sbin/livecd-mkinitrd if [ $UP_installed ]; then depmod -a ${KERNEL_VERSION} /usr/sbin/livecd-mkinitrd --fstab=$NEW/etc/fstab \ $NEW//boot/initrd-${KERNEL_VERSION}.img ${KERNEL_VERSION} if [ ! -e $NEW/boot/initrd-${KERNEL_VERSION}.img ]; then echo "ERROR: Failed to create $NEW/boot/initrd-${KERNEL_VERSION}.img" exit_now 1 fi fi if [ $SMP_installed ]; then depmod -a ${KERNEL_VERSION}smp /usr/sbin/livecd-mkinitrd --fstab=$NEW/etc/fstab \ $NEW/boot/initrd-${KERNEL_VERSION}smp.img ${KERNEL_VERSION}smp if [ ! -e $NEW/boot/initrd-${KERNEL_VERSION}smp.img ]; then echo "ERROR: Failed to create $NEW/boot/initrd-${KERNEL_VERSION}smp.img" exit_now 1 fi fi echo "done."; echo ### remove LiveCD init.d scripts ### ----------------------------------------------------------- for file in $LIVECD_INIT_SCRIPTS; do rm -f $NEW/etc/rc.d/init.d/$file for n in 0 1 2 3 4 5 6; do rm -f $NEW/etc/rc.d/rc${n}.d/*$file done done ### restore cronjobs ### ----------------------------------------------------------- mv $NEW/etc/cron_backup/sysstat $NEW/etc/cron.d/ 2>/dev/null mv $NEW/etc/cron_backup/cfengine $NEW/etc/cron.d/ 2>/dev/null mv $NEW/etc/cron_backup/psi-cronjobs $NEW/etc/cron.d/ 2>/dev/null mv $NEW/etc/cron_backup/00-makewhatis.cron.weekly $NEW/etc/cron.weekly/00-makewhatis.cron 2>/dev/null mv $NEW/etc/cron_backup/* $NEW/etc/cron.daily/ 2>/dev/null ### prepare chroot to $NEW ### ----------------------------------------------------------- mount --bind /dev $NEW/dev mount --bind /sys $NEW/sys mount -t proc proc $NEW/proc ### turn on kudzu again ### ----------------------------------------------------------- chroot $NEW chkconfig kudzu on ### turn on check_update again (only at PSI) ### ----------------------------------------------------------- chroot $NEW chkconfig check_update on 2>/dev/null ### fix some services which were disabled ### because of diskless NFS client ### ----------------------------------------------------------- if [ -e /$MOUNTDIR/service.on ]; then cat /$MOUNTDIR/service.on | while read $serv; do chroot $NEW chkconfig $serv on done fi ### remove some files ### ----------------------------------------------------------- rm -rf $NEW/usr/share/applications/livecd-install-gui.desktop rm -rf $NEW/usr/share/applications/save-localdata.desktop ### remove RPMs that can break future updates ### ----------------------------------------------------------- if [ ! $NORPMREMOVE ]; then echo "Remove RPMs that may break future updates ..." chroot $NEW rpm -qa 2>/dev/null > /tmp/rpmlist # Scientific Linux RPMs RPMSTOREMOVE="$RPMS_TO_REMOVE $RPMS_TO_REMOVE_SL" # PSI Scientific Linux RPMs if [ -e /etc/sysconfig/psi ]; then RPMSTOREMOVE="$RPMS_TO_REMOVE $RPMS_TO_REMOVE_PSI" fi for rpm in $RPMSTOREMOVE; do rpms_remove=$( cat /tmp/rpmlist | grep "^$rpm" ) for rpm_remove in $rpms_remove; do chroot $NEW rpm -e --nodeps $rpm_remove >/dev/null 2>&1 [ "$?" = "0" ] && echo " removing $rpm_remove" done done echo "done."; echo fi ### disable nvidia driver ### ----------------------------------------------------------- # not in case of a PSI installation if [ ! -e /etc/sysconfig/psi ]; then if [ -e $NEW/etc/X11/xorg.conf.nv_SAVED ]; then echo "Remove nvidia driver and correct xorg.conf ..." # correct xorg.conf sed -i "s/#nv_SAVED //" $NEW/etc/X11/xorg.conf sed -i "/.*Driver.*nvidia.*/d" $NEW/etc/X11/xorg.conf # disable nvidia libs (if not yet done by rpm -e) LIB=lib [ $( arch ) = "x86_64" ] && LIB=lib64 mv -f $NEW/usr/X11R6/$LIB/modules/extensions/xxx.libGLcore.a.saved_by_nvidia \ $NEW/usr/X11R6/$LIB/modules/extensions/libGLcore.a 2>/dev/null mv -f $NEW/usr/X11R6/$LIB/modules/extensions/xxx.libglx.a.saved_by_nvidia \ $NEW/usr/X11R6/$LIB/modules/extensions/libglx.a 2>/dev/null rm -f $NEW/usr/X11R6/$LIB/modules/extensions/libglx.so rm -f $NEW/usr/X11R6/$LIB/libGL.so* rm -f $NEW/usr/$LIB/libGLcore.so echo "done."; echo fi fi ### umount $INSTALL_PART ### ----------------------------------------------------------- umount $NEW/dev umount $NEW/sys umount $NEW/proc umount $INSTALL_PART ### print summary ### ----------------------------------------------------------- echo "--------------------------------------------------------------" echo " LiveCD installed on partition $INSTALL_PART" [ "$SWAP_PART" ] && echo " Partition $SWAP_PART will be used as swap partition" echo [ ! $NOGRUB ] && echo " GRUB installed in Master Boot Record (MBR) of $MBR_DEV" [ ! $NOGRUB ] && echo " MBR saved as $MBR_FILENAME on $INSTALL_PART and in /tmp" [ ! $NOGRUB ] && echo " If you have to restore MBR, execute under Linux:" [ ! $NOGRUB ] && echo " # dd if=$MBR_FILENAME of=$MBR_DEV bs=512 count=1" echo [ $WIN_PART ] && echo " Entry created in grub.conf for Windows partition $WIN_PART" echo "--------------------------------------------------------------" echo "End of $SCRIPTNAME" echo