#!/bin/bash # some default settings - gets overidden with the profile config CDPROFILE="$2" [[ -z ${CDPROFILE} ]] && CDPROFILE="default" LIVECDROOT="/mnt/MLIVECDBUILD/${CDPROFILE}" CDCHROOTDIR="${LIVECDROOT}/chroot" CDISONAME="livecd-${CDPROFILE}.iso" CDISOROOT="${LIVECDROOT}/isoroot" CDKERNELNAME="magelive" CDHOSTNAME="livecd-${CDPROFILE}" MAGERC="/etc/mage.rc" MAGE_PROFILE="$(basename $(readlink /etc/mage-profile))" #TOOLCHAIN=toolchain BASESYSTEM=livecdsystem26 CDID="mlcd-$(date +%F-%k%M)" # global profile pathes PROFILES_DIR="/usr/lib/mlivecdbuild/profiles" GLOBAL_PROFILE="${PROFILES_DIR}/global" # get full path to isolinux.bin, may vary an multilib systems if [[ -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 get_profile() { local file="$1" if [[ -z ${file} ]] || [[ ! -e ${PROFILES_DIR}/${CDPROFILE}/${file} ]] then echo "${GLOBAL_PROFILE}/${file}" return 0 fi echo "${PROFILES_DIR}/${CDPROFILE}/${file}" } bootstrap_system() { mage-bootstrap \ --root "${CDCHROOTDIR}" \ --magerc "${MAGERC}" \ --profile "${MAGE_PROFILE}" \ --toolchain "${TOOLCHAIN}" \ --basesystem "${BASESYSTEM}" \ || 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 ]] && [[ -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 # only on sysvinit or busybox systems if [[ -x ${CDCHROOTDIR}/sbin/rc-config ]] then install -m 0644 $(get_profile inittab) ${CDCHROOTDIR}/etc/inittab || die 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 ... # # add hardware detection # if [[ -x ${CDCHROOTDIR}/sbin/rc-config ]] # then # MROOT="${CDCHROOTDIR}" rc-config add hwdetect || die "rc add hwdetect" # fi # 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 ... # 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 ... 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} 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() { echo Installing Bootloader ... # iso linux binary install -d ${CDISOROOT}/isolinux install ${ISOLINUX_BIN} ${CDISOROOT}/isolinux || die # kernel local kimg="$(basename $(readlink ${CDCHROOTDIR}/boot/vmlinuz))" install ${CDCHROOTDIR}/boot/${kimg} ${CDISOROOT}/isolinux/${CDKERNELNAME} || die install -m 0644 $(get_profile isolinux.cfg) ${CDISOROOT}/isolinux || die install -m 0644 $(get_profile boot.lss) ${CDISOROOT}/isolinux || die install -m 0644 $(get_profile boot.msg) ${CDISOROOT}/isolinux || die install -m 0644 $(get_profile help.msg) ${CDISOROOT}/isolinux || die return 0 } generate_initrd() { local CHROOTSH="$(mktemp -p ${CDCHROOTDIR})" 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 # 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 } generate_iso() { echo Generating ISO Image ... install -d ${CDISOROOT} pushd ${CDISOROOT} && mkisofs -rock \ -full-iso9660-filenames \ -allow-leading-dots \ -disable-deep-relocation \ -output ${LIVECDROOT}/${CDISONAME} \ -eltorito-boot isolinux/isolinux.bin \ -eltorito-catalog isolinux/boot.cat \ -no-emul-boot \ -boot-load-size 4 \ -boot-info-table \ -volid "${CDID}" \ ${CDISOROOT} #&> /dev/null popd } enter_livecd() { 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 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