--- trunk/mlivecdbuild/mlivecdbuild2.sh 2006/03/05 02:18:28 348 +++ trunk/mlivecdbuild/mlivecdbuild2.sh 2011/07/29 11:14:07 1446 @@ -1,7 +1,7 @@ #!/bin/bash # some default settings - gets overidden with the profile config -CDPROFILE="$1" +CDPROFILE="$2" [[ -z ${CDPROFILE} ]] && CDPROFILE="default" LIVECDROOT="/mnt/MLIVECDBUILD/${CDPROFILE}" CDCHROOTDIR="${LIVECDROOT}/chroot" @@ -19,6 +19,17 @@ PROFILES_DIR="/usr/lib/mlivecdbuild/profiles" GLOBAL_PROFILE="${PROFILES_DIR}/global" +# get full path to isolinux.bin, may vary on multilib systems +if [[ -f /usr/share/syslinux/isolinux.bin ]] +then + ISOLINUX_BIN=/usr/share/syslinux/isolinux.bin +elif [[ -f /usr/lib64/mkinitrd/isolinux.bin ]] +then + ISOLINUX_BIN=/usr/lib64/mkinitrd/isolinux.bin +else + ISOLINUX_BIN=/usr/lib/mkinitrd/isolinux.bin +fi + die() { echo "ERROR: $@"; exit 1; } # get_profile $filename @@ -46,48 +57,258 @@ || die "bootstrapping toolchain" } +custom_services() +{ + local cmd="$1" + local services="$2" + local systemdcmd + + case ${cmd} in + add|del|default) + # add given services from profile + if [[ -n ${services} ]] + then + local i + for i in ${services} + do + # systemd + if [[ -x ${CDCHROOTDIR}/sbin/systemctl ]] + then + case ${cmd} in + add) chroot ${CDCHROOTDIR} systemctl enable ${i} ;; + del) chroot ${CDCHROOTDIR} systemctl disable ${i} ;; + esac + fi + # busybox and sysvinit + if [[ -x ${CDCHROOTDIR}/sbin/rc-config ]] + then + MROOT="${CDCHROOTDIR}" rc-config ${cmd} ${i} || die "rc ${cmd} ${i}" + fi + done + fi + ;; + *) die "custom_services: unkown command ${cmd}";; + esac +} + +add_initrc() +{ + local var="$1" + + # sanity checks + [[ -z ${CDCHROOTDIR} ]] && die "\$CDCHROOTDIR not given." + echo "${var}" >> ${CDCHROOTDIR}/.installrc || die "add_initrc() adding \$var" +} + +custom_packages() +{ + local cmd="$1" + local packages="$2" + + case ${cmd} in + install|uninstall) + if [[ -n ${packages} ]] + then + :> ${CDCHROOTDIR}/.installrc + + # respect proxies + [[ -n ${http_proxy} ]] && add_initrc "export http_proxy=${http_proxy}" + [[ -n ${ftp_proxy} ]] && add_initrc "export ftp_proxy=${ftp_proxy}" + [[ -n ${no_proxy} ]] && add_initrc "export no_proxy=${no_proxy}" + + # do not auto-start any services! + add_initrc "export MAGE_BOOTSTRAP=true" + add_initrc 'die() { if [ $? -eq 1 ]; then echo "ERROR: $@"; exit 1; fi; }' + + local i + for i in ${packages} + do + add_initrc "mage ${cmd} ${i} || die ${i}" + done + add_initrc "mage clean" + + # now run the .installrc script + mount -t proc proc ${CDCHROOTDIR}/proc || die "mount proc" + mount -t sysfs sysfs ${CDCHROOTDIR}/sys || die "mount sys" + mount -o bind /dev ${CDCHROOTDIR}/dev || die "mount dev" + chroot ${CDCHROOTDIR} /bin/bash -i /.installrc || die "chr00ting" + umount ${CDCHROOTDIR}/dev || die "umount dev" + umount ${CDCHROOTDIR}/proc || die "umount proc" + umount ${CDCHROOTDIR}/sys || die "umount sys" + [ -f ${CDCHROOTDIR}/.installrc ] && rm ${CDCHROOTDIR}/.installrc + fi + ;; + *) die "custom_packages: unkown command ${cmd}";; + esac +} + +read_config() +{ + local file="$1" + local pkg + + ( cat ${file}; echo ) | while read pkg + do + case "${pkg}" in + \#*|"") continue ;; + esac + echo "${pkg}" + done +} + prepare_iso() { echo Preparing LiveCD ISO Image ... # fixes some issues with xfree/xorg xkb - if [ -L "${CDCHROOTDIR}/etc/X11/xkb" -a -d "/usr/X11R6/lib/X11/xkb" ] + if [[ -L ${CDCHROOTDIR}/etc/X11/xkb ]] && [[ -d /usr/X11R6/lib/X11/xkb ]] then rm ${CDCHROOTDIR}/etc/X11/xkb || die mv ${CDCHROOTDIR}/usr/X11R6/lib/X11/xkb ${CDCHROOTDIR}/etc/X11 || die ln -s ../../../../etc/X11/xkb ${CDCHROOTDIR}/usr/X11R6/lib/X11/xkb || die fi - install -m 0644 $(get_profile inittab) ${CDCHROOTDIR}/etc/inittab || die + # only on sysvinit or busybox systems + if [[ -x ${CDCHROOTDIR}/sbin/rc-config ]] + then + install -m 0644 $(get_profile inittab) ${CDCHROOTDIR}/etc/inittab || die + fi + # check lock group on systemd systems + if [[ -x ${CDCHROOTDIR}/bin/systemctl ]] + then + if [[ -z $(chroot ${CDCHROOTDIR} getent group lock) ]] + then + chroot ${CDCHROOTDIR} groupadd -g 54 lock + fi + fi install -m 0644 $(get_profile fstab) ${CDCHROOTDIR}/etc/fstab || die install -m 0644 $(get_profile motd) ${CDCHROOTDIR}/etc/motd || die install -m 0644 $(get_profile issue) ${CDCHROOTDIR}/etc/issue || die + install -m 0644 $(get_profile net.eth0) ${CDCHROOTDIR}/etc/conf.d/net.eth0 || die echo "${CDHOSTNAME}" > ${CDCHROOTDIR}/etc/hostname || die echo Setting up services ... - # change mountfs with mountfslivecd - MROOT="${CDCHROOTDIR}" rc-config del mountfs || die "rc del mountfs" - MROOT="${CDCHROOTDIR}" rc-config add mountfslivecd || die "rc add mountfslivecd" - - # add hardware detection - MROOT="${CDCHROOTDIR}" rc-config add hwdetect || die "rc add hwdetect" +# # add hardware detection +# if [[ -x ${CDCHROOTDIR}/sbin/rc-config ]] +# then +# MROOT="${CDCHROOTDIR}" rc-config add hwdetect || die "rc add hwdetect" +# fi # del checkfs - MROOT="${CDCHROOTDIR}" rc-config del checkfs || die "rc del checkfs" + if [[ -x ${CDCHROOTDIR}/sbin/rc-config ]] + then + MROOT="${CDCHROOTDIR}" rc-config del checkfs || die "rc del checkfs" + fi + + # add custom packages + [[ -n ${ADD_PACKAGES} ]] && custom_packages install "${ADD_PACKAGES}" + [ -f $(get_profile add_packages) ] && custom_packages install "$(read_config $(get_profile add_packages))" + + # del custom packages + [[ -n ${DEL_PACKAGES} ]] && custom_packages uninstall "${DEL_PACKAGES}" + [ -f $(get_profile del_packages) ] && custom_packages uninstall "$(read_config $(get_profile del_packages))" + + # add given services from profile + [[ -n ${ADD_SERVICES} ]] && custom_services add "${ADD_SERVICES}" + [ -f $(get_profile add_services) ] && custom_services add "$(read_config $(get_profile add_services))" + + # del given services from profile + [[ -n ${DEL_SERVICES} ]] && custom_services del "${DEL_SERVICES}" + [ -f $(get_profile del_services) ] && custom_services del "$(read_config $(get_profile del_services))" + + # setup default runlevel + [[ -n ${DEFAULT_RUNLEVEL} ]] && custom_services default "${DEFAULT_RUNLEVEL}" + + if [ -f $(get_profile prepare_custom) ] + then + echo Running custom user script ... + source $(get_profile prepare_custom) || die "running custom user script" + fi echo Cleaning unwanted files ... - :> ${CDCHROOTDIR}/etc/mtab || die "whiping /etc/mtab" + # do this only if not a symlink! + if [[ ! -L ${CDCHROOTDIR}/etc/mtab ]] + then + :> ${CDCHROOTDIR}/etc/mtab || die "whiping /etc/mtab" + fi + [ -f ${CDCHROOTDIR}/root/.bash_history ] && rm ${CDCHROOTDIR}/root/.bash_history } generate_rootfs() { + local loopdev + local size + + if [ -f ${LIVECDROOT}/loop/LiveOS/ext3fs.img ] + then + rm ${LIVECDROOT}/loop/LiveOS/ext3fs.img || die + fi + if [ -f ${CDISOROOT}/LiveOS/squashfs.img ] + then + rm ${CDISOROOT}/LiveOS/squashfs.img + fi + if [ -f ${CDISOROOT}/livecdrootfs.sqsh ] + then + rm ${CDISOROOT}/livecdrootfs.sqsh + fi + echo Generating squashfs compressed rootfs loopfile ... - mksquashfs ${CDCHROOTDIR} ${LIVECDROOT}/livecdrootfs.sqsh #>/dev/null 2>&1 + if [[ -x ${CDCHROOTDIR}/sbin/dracut ]] + then + install -d ${LIVECDROOT}/loop/{LiveOS,mnt} || die + + # get the actual size of the chroot + size=$(du -s chroot | sed 's:^\(.*\)[[:space:]].*:\1:') + + # generate a ext3fs file for devicemapper + dd if=/dev/zero of=${LIVECDROOT}/loop/LiveOS/ext3fs.img bs=1024 count=$(( ${size} + 10 )) || die + # create a filesystem + mkfs.ext3 -L "_${CDID}_EXT3" -m 1 -b 1024 -F ${LIVECDROOT}/loop/LiveOS/ext3fs.img || die + # set mount_counts and check_intervals to 0 + # set dir_index top, to speed up thing with hashed b-trees + # allow acls too + tune2fs -c0 -i0 -Odir_index -ouser_xattr,acl ${LIVECDROOT}/loop/LiveOS/ext3fs.img || die + + # losetup the device + loopdev=$(losetup -f) + [[ -z ${loopdev} ]] && die "No unused loopdev found. Maybe you want 'modprobe loop'?" + + # mount the image + losetup ${loopdev} ${LIVECDROOT}/loop/LiveOS/ext3fs.img || die + mount ${loopdev} ${LIVECDROOT}/loop/mnt || die + + # copy everything to the image file and preserve permissions + ( cd ${CDCHROOTDIR} && tar cpf - . ) | ( cd ${LIVECDROOT}/loop/mnt && tar xvpf - ) + + # now umount everything and create the squashfs image + umount ${LIVECDROOT}/loop/mnt || die + losetup -d ${loopdev} || die + # remove mount to not ending up in the squashfs image + if [[ -d ${LIVECDROOT}/loop/mnt ]] + then + rm -r ${LIVECDROOT}/loop/mnt || die + fi + mksquashfs ${LIVECDROOT}/loop ${LIVECDROOT}/livecdrootfs.sqsh || die + + # final cleanup + if [[ -d ${LIVECDROOT}/loop ]] + then + rm -r ${LIVECDROOT}/loop || die + fi + else + mksquashfs ${CDCHROOTDIR} ${LIVECDROOT}/livecdrootfs.sqsh || die + fi echo Moving rootfs loopfile to isoroot ... install -d ${CDISOROOT} - mv ${LIVECDROOT}/livecdrootfs.sqsh ${CDISOROOT} + if [[ -x ${CDCHROOTDIR}/sbin/dracut ]] + then + install -d ${CDISOROOT}/LiveOS + mv ${LIVECDROOT}/livecdrootfs.sqsh ${CDISOROOT}/LiveOS/squashfs.img + else + mv ${LIVECDROOT}/livecdrootfs.sqsh ${CDISOROOT} + fi } install_bootloader() @@ -96,7 +317,7 @@ # iso linux binary install -d ${CDISOROOT}/isolinux - install /usr/lib/mkinitrd/isolinux.bin ${CDISOROOT}/isolinux || die + install ${ISOLINUX_BIN} ${CDISOROOT}/isolinux || die # kernel local kimg="$(basename $(readlink ${CDCHROOTDIR}/boot/vmlinuz))" @@ -113,17 +334,31 @@ generate_initrd() { local CHROOTSH="$(mktemp -p ${CDCHROOTDIR})" - echo "DEBUG: ${CHROOTSH}" + + is_loc_mounted "${CDCHROOTDIR}/sys" || mount -t sysfs sysfs ${CDCHROOTDIR}/sys + is_loc_mounted "${CDCHROOTDIR}/proc" || mount -t proc proc ${CDCHROOTDIR}/proc + is_loc_mounted "${CDCHROOTDIR}/dev" || mount -o bind /dev ${CDCHROOTDIR}/dev echo Generating initrd image ... echo '#!/bin/bash' > ${CHROOTSH} || die + echo 'export LC_ALL=C' >> ${CHROOTSH} || die echo 'kv="$(readlink /boot/vmlinuz)"' >> ${CHROOTSH} || die echo 'kv="${kv/kernel-}/"' >> ${CHROOTSH} || die - echo 'mkinitrd-livecd -f --initramfs /initrd.gz ${kv}' >> ${CHROOTSH} || die + # prefer dracut + echo 'if [[ -x /sbin/dracut ]]' >> ${CHROOTSH} || die + echo 'then' >> ${CHROOTSH} || die + echo ' dracut -v -f /initrd.gz ${kv}' >> ${CHROOTSH} || die + echo 'else' >> ${CHROOTSH} || die + echo ' mkinitrd-livecd -f --initramfs /initrd.gz ${kv}' >> ${CHROOTSH} || die + echo 'fi' >> ${CHROOTSH} || die chmod +x ${CHROOTSH} || die chroot ${CDCHROOTDIR} /$(basename ${CHROOTSH}) || die [[ -f ${CHROOTSH} ]] && rm ${CHROOTSH} || die + is_loc_mounted "${CDCHROOTDIR}/dev" && umount ${CDCHROOTDIR}/dev + is_loc_mounted "${CDCHROOTDIR}/proc" && umount ${CDCHROOTDIR}/proc + is_loc_mounted "${CDCHROOTDIR}/sys" && umount ${CDCHROOTDIR}/sys + # move initrd to isoroot install -d ${CDISOROOT}/isolinux || die mv ${CDCHROOTDIR}/initrd.gz ${CDISOROOT}/isolinux || die @@ -151,24 +386,84 @@ enter_livecd() { - mount -t sysfs sysfs ${CDCHROOTDIR}/proc - mount -t proc proc ${CDCHROOTDIR}/proc - mount -o bind /dev ${CDCHROOTDIR}/dev + is_loc_mounted "${CDCHROOTDIR}/sys" || mount -t sysfs sysfs ${CDCHROOTDIR}/sys + is_loc_mounted "${CDCHROOTDIR}/proc" || mount -t proc proc ${CDCHROOTDIR}/proc + is_loc_mounted "${CDCHROOTDIR}/dev" || mount -o bind /dev ${CDCHROOTDIR}/dev chroot ${CDCHROOTDIR} \ /usr/bin/env -i \ HOME=/root \ TERM=$TERM PS1='\u:\w\$ ' \ PATH=/bin:/usr/bin:/sbin:/usr/sbin \ + http_proxy=${http_proxy} \ + ftp_proxy=${ftp_proxy} \ + no_proxy=${no_proxy} \ /bin/bash -i + + is_loc_mounted "${CDCHROOTDIR}/dev" && umount ${CDCHROOTDIR}/dev + is_loc_mounted "${CDCHROOTDIR}/proc" && umount ${CDCHROOTDIR}/proc + is_loc_mounted "${CDCHROOTDIR}/sys" && umount ${CDCHROOTDIR}/sys +} + +is_loc_mounted() +{ + local filesys + local i + filesys=$1 + + i="$(cat /proc/mounts | grep " ${filesys} " | cut -d ' ' -f2)" + [[ ${i} != ${filesys} ]] && return 1 + + return 0 } +trap_exit() +{ + is_loc_mounted "${CDCHROOTDIR}/dev" && umount ${CDCHROOTDIR}/dev + is_loc_mounted "${CDCHROOTDIR}/proc" && umount ${CDCHROOTDIR}/proc + is_loc_mounted "${CDCHROOTDIR}/sys" && umount ${CDCHROOTDIR}/sys +} + +usage() +{ + echo "Usage: $(basename $0) [command] [profile] ..." + echo + echo "Commands:" + echo " bootstrap - bootstraps the rootfs for the livecd" + echo " prepare - prepare the rootfs to run from a livecd" + echo " rootfs - generates the squashfs rootfs image" + echo " initrd - generates a livecd suitable initrd" + echo " bootloader - installs the bootloader" + echo " isogen - generate the final livecd iso image" + echo " all - runs all tasks to get a livecd from zero" + echo " enter - enters the rootfs of a livecd" + echo + echo " for example '$(basename $0) all default'" + echo " creates a livecd using the default profile." + echo +} + +# set some proper traps +trap "trap_exit" SIGINT SIGQUIT + # source profile config - overrides all other vars [ -f ${PROFILES_DIR}/${CDPROFILE}/config ] && . ${PROFILES_DIR}/${CDPROFILE}/config -bootstrap_system -prepare_iso -generate_rootfs -generate_initrd -install_bootloader -generate_iso +case $1 in + bootstrap) bootstrap_system;; + prepare) prepare_iso;; + rootfs) generate_rootfs;; + initrd) generate_initrd;; + bootloader) install_bootloader;; + isogen) generate_iso;; + all) + bootstrap_system + prepare_iso + generate_rootfs + generate_initrd + install_bootloader + generate_iso + ;; + enter) enter_livecd ;; + *|'') usage;; +esac