#!/bin/bash # LUBUNTU USB CREATOR aka LUC (run as sudo only) # Up to date version : https://doc.ubuntu-fr.org/tutoriel/lubuntu_usb_creator # v1.4 lnj 22/04/2015 # USAGE : luc_onetouch_install.sh [DEV [ISO]] # Where optional DEV is device disk (not a partition) and optional ISO an ISO file. # Supported versions : https://doc.ubuntu-fr.org/tutoriel/lubuntu_usb_creator?do=edit&rev=0#plateformes_supportees # History : # - v1.4 lnj 22/04/2015 : adding needed dependency # - v1.3 lnj 15/04/2015 : adding needed dependency squashfs-tools # - v1.2 lnj 12/04/2015 # Different links which help me : # http://askubuntu.com/questions/397481/how-to-make-a-persistent-live-ubuntu-usb-with-more-than-4gb # http://david.hautbois.free.fr/wordpress/index.php/175-how-to-customize-your-ubuntu-live-usb-stick # http://day-to-day-stuff.blogspot.fr/2011/03/on-making-custom-ubuntu-bootable-usb.html # more - boot process : https://wiki.archlinux.org/index.php/syslinux # http://doc.ubuntu-fr.org/tutoriel/live_usb_install4 # http://www.linux.com/community/blogs/133-general-linux/420179-creating-a-debian-live-usb-flash-drive-with-persistence-for-non-techies # https://help.ubuntu.com/community/USB%20Installation%20Media) ################################## CHOOSE HDD ##################################### # to retrieve parts and disks : http://www.labtestproject.com/using_linux/partition_hard_disk_using_fdisk_command_on_linux_fedora_system # lsblk -o NAME,TYPE,FSTYPE,LABEL,SIZE,MOUNTPOINT ################################ STATIC SETTINGS ################################## # ------------------------------- FUNCTIONAL -------------------------------------- # DEV : the DEV disk used to install Live USB (not part) ; can be given from $1 arg # See lsblk command above to determine the target disk # !!! Warning: DEV data will be permanently deleted (no possible return ) !!! # ISO : ISO file location (only absolute paths is possible) ; i.e. '/ISO/tux.iso' # ME : my short name user # ME_FULL : my full name user # NET_ADDRESS : static IP address wanted in my network # !!! Becareful : possible IP conflict with other PC, especially DHCP scope !!! # NET_NETMASK : my network mask # NET_GATEWAY : the accessible gateway (i.e. to join the Internet) # NET_DNS : an accessible DNS server to allow internet browsing and apt-get jobs too DEV=/dev/sde # !!! Warning: DEV data will be permanently deleted (no possible return ) !!! ISO='/ISO/lubuntu-14.10-desktop-i386.iso' ME=user ME_FULL='User' NET_ADDRESS=192.168.0.3 NET_NETMASK=255.255.255.0 NET_GATEWAY=192.168.0.254 NET_DNS=8.8.8.8 # ------------------------------- PRE-CONFIGURED ----------------------------------- # USB_LABEL : partition 1 label [default : L_LUBUNTU (Live LUBUNTU)] # USB_PART1_SIZE : size for the partition 1 # [recommended : USB_PART1_SIZE=1G - for 1 GB, see man parted search unit] # USB_PART2_SIZE : size for the partition 2 # [recommended : USB_PART2_SIZE=100% - for all the remaining space] # If we want a 3rd part or more, not give 100% or specify in absolute size # for example 10GB (see man parted and search unit) # LIVE_USB_BOOT_MESSAGE : welcome boot message [dft : 'Lubuntu USB Live Persistant'] # LIVE_USB_BOOT_QUIET : 0/1 (0 => verbose/no splash, 1 => quiet with splash) # [default : 1] # ME_DEFAULT_PASSWORD : my simple default password (change it for first logon) # !!! Becareful : password in clear, so give a temp simple password !!! # [default : lubuntu] # EMBED_PACKETS : list of packets automatically installed at 1st boot # separate all packets by a space # i.e. EMBED_PACKETS='htop vim' # [default : ''] # Nota : ssh is later included by default # EMBED_VNC : 0/1 embed VNC for remote desktop (0 => no, 1 => yes) # http://adept1formatique.unblog.fr/2013/08/12/bureau-a-distance-avec-lubuntu/ # [default : 1] # UPDATE_OS : 0/1 update OS (take a while) (0 => no, 1 => yes) # [default : 1] # INSTALL_APP_LANG : 0/1 install language for apps (take a while) (0 => no, 1 => yes) # [default : 1] USB_LABEL=L_LUBUNTU USB_PART1_SIZE=1G USB_PART2_SIZE=100% LIVE_USB_BOOT_MESSAGE='Lubuntu USB Live Persistant' LIVE_USB_BOOT_QUIET=1 ME_DEFAULT_PASSWORD=lubuntu # !!! Becareful : password in clear, so give a temp simple password !!! EMBED_PACKETS='' EMBED_VNC=1 UPDATE_OS=1 INSTALL_APP_LANG=1 # ---------------------------------------------------------------------- # For future version # # DEFAULT_LIVE_USB_USER : default live session user # NETWORK_MANAGER_ACTIVE : 0/1 indicate how to manage network (0 => ifup, 1 => NM) # [default : 0] # LOCALE : embed locale for keyboard, live session boot and other stuff # [default : FR so 'locale=fr_FR.UTF-8 console-setup/layoutcode=fr' # LANGUAGE_SUPPORT : make apps language with the right language support # [default : fr] # DATE_TIME_ZONE : synchro Time Zone (http://askubuntu.com/a/594186) # [default : Europe/Paris] # WAITING_REBOOT_TITLE : title to display in the terminal before reboot # [default : 'Patienter avant le redémarrage...'] DEFAULT_LIVE_USB_USER=lubuntu NETWORK_MANAGER_ACTIVE=0 LOCALE='locale=fr_FR.UTF-8 console-setup/layoutcode=fr' LANGUAGE_SUPPORT=fr DATE_TIME_ZONE=Europe/Paris WAITING_REBOOT_TITLE='Patienter avant le redémarrage...' # Embed ssh to install EMBED_PACKETS="ssh $EMBED_PACKETS" # Embed VNC to install if [ $EMBED_VNC -eq 1 ] ; then EMBED_PACKETS="$EMBED_PACKETS vino x11vnc" fi # Quiet or not if [ $LIVE_USB_BOOT_QUIET -eq 1 ] ; then LIVE_USB_BOOT_QUIET='quiet splash' else LIVE_USB_BOOT_QUIET= fi # Manage network with NM or ifup if [ $NETWORK_MANAGER_ACTIVE -eq 1 ] ; then NETWORK_MANAGER_ACTIVE= else NETWORK_MANAGER_ACTIVE='ip=frommedia' fi # Define customized colors : http://stackoverflow.com/a/5947802 C_red='\033[1;31m' C_blue='\033[0;34m' C_green='\033[0;32m' C_yellow='\033[1;33m' C_NC='\033[0m' # Echoing all steps (usage : echof "..." [color]) # a=( "$@" ) ... ${a[1]} because ${$2} does not work (args to array) # http://stackoverflow.com/a/18041780 + http://stackoverflow.com/a/12711837 function echof () { if [ "$2" ] ; then a=( "$@" ) ; echo -e "\n${a[1]}=> $1${C_NC}\n" ; else echo -e "\n${C_yellow}=> $1${C_NC}\n" ; fi } ############################## PROTECT DATA ############################# LUC_MNT=~/tmp/mnt # If we give arg1 it will become DEV if [ "$1" ] ; then DEV=$1 fi # If we give arg2 it will become ISO if [ "$2" ] ; then ISO="$2" fi # Get DISK part of DEV, so /dev/sde gives sde DISK=`echo $DEV |sed "s/.*\/\([a-z]*\)$/\1/"` # If DEV is not a real device disk IS_DISK=`lsblk -o NAME,TYPE,FSTYPE,LABEL,SIZE,MOUNTPOINT |grep ^$DISK` if [ ! "$IS_DISK" ] ; then echo "Error : $DEV is not a valid disk !" exit 1 fi # If ISO file does not exist if [ ! -f "$ISO" ] ; then echo "Error : $ISO ISO file does not exist !" exit 2 fi # Infos about selected device echo -e "\n${C_yellow}Block device of ${C_blue}$DEV${C_NC} :" RES=`lsblk -o NAME,TYPE,FSTYPE,LABEL,SIZE,MOUNTPOINT |sed "1p;/$DISK/!d"` echo -e "${C_green}$RES${C_NC}" mkdir -p $LUC_MNT # For each partition we display the partial content for X in `echo $DEV`* do if [ $X != $DEV ] ; then echo -e "\n${C_yellow}Partial content of ${C_blue}$X${C_NC} :" if [ "`mount |grep $X`" ] ; then FOLDER=`mount |grep $X |cut -f 3 -d " "` CONTENT=`ls -alF $FOLDER | head` else mount $X $LUC_MNT CONTENT=`ls -alF $LUC_MNT | head` umount -l $LUC_MNT fi echo -e "$CONTENT" fi done rmdir $LUC_MNT # Confirm or not : http://stackoverflow.com/a/1885534 MSG="\n${C_red}You are about destroying all data from ${C_blue}$DEV${C_red}" echo -e "$MSG (no return is possible) !${C_NC}" read -p "Are you sure (y/[N]) ? " -r echo if [[ ! $REPLY =~ ^[y]$ ]] then exit 0 fi # do dangerous stuff #echo Destroy en cours... ################################ PREPARE ################################ # LUC paths LUC_PATH=~/luc LUC_LIVEUSB_PATH=~/luc/liveusb LUC_ISO_PATH=~/luc/iso LUC_SQUASHFS_PATH=~/luc/squashfs LUC_CUSTOM_SQUASHFS_PATH=~/luc/custom-squashfs # Scripts and other stuff paths SCRIPTS_PATH=$LUC_LIVEUSB_PATH/scripts RUNME1ST_ROOT_PATH=scripts/runme1st_from_ext.sh RUNME1ST_EXT_PATH=/cdrom/$RUNME1ST_ROOT_PATH SYSLINUX_EXT_PATH=/cdrom/syslinux/syslinux.cfg RESET_ROOT_PATH=scripts/reset.sh RESET_EXT_PATH=/cdrom/$RESET_ROOT_PATH RUNMELAST_PATH=/home/runmelast.sh # Escaped string path RUNME1ST_EXT_PATH_ESC=${RUNME1ST_EXT_PATH//\//\\\/} RUNMELAST_PATH_ESC=${RUNMELAST_PATH//\//\\\/} # debug : Start / End / exit to let start here and move end and exit #:< Download dependencies" apt-get install -y syslinux mtools parted squashfs-tools echof "PREPARE > Unmount all" umount $DEV* umount $LUC_ISO_PATH umount $LUC_LIVEUSB_PATH umount $LUC_SQUASHFS_PATH rm -rf $LUC_PATH echof "PREPARE > MBR + partitions" # man parted : http://linux.die.net/man/8/parted # sample : http://stackoverflow.com/questions/10519486/valid-arguments-for-parted # 100% remaining space http://forums.gentoo.org/viewtopic-t-586478-start-0.html echof "PREPARE > MBR MS-DOS (force to change)" parted "$DEV" mklabel -s "msdos" msg="PREPARE > part1 FAT32, $USB_PART1_SIZE, format FAT32, label $USB_LABEL," echof "$msg flag boot + lba" parted -a cylinder "$DEV" mkpart primary fat32 1 $USB_PART1_SIZE mkfs.vfat -n "$USB_LABEL" -I "$DEV"1 -F 32 parted "$DEV" set 1 boot on parted "$DEV" set 1 lba on msg="PREPARE > part2 EXT4, $USB_PART2_SIZE remaining space, format EXT4," echof "$msg label 'casper-rw'" parted -a cylinder "$DEV" mkpart primary ext4 $USB_PART1_SIZE $USB_PART2_SIZE mkfs.ext4 -L 'casper-rw' "$DEV"2 echof "PREPARE > Live USB Building" echof "PREPARE > Live USB Building > Prepare working dir skeleton" rm -rf $LUC_PATH mkdir $LUC_PATH mkdir $LUC_LIVEUSB_PATH mkdir $LUC_ISO_PATH mkdir $LUC_SQUASHFS_PATH mkdir $LUC_CUSTOM_SQUASHFS_PATH echof "PREPARE > Live USB Building > Mount of USB device" mount "$DEV"1 $LUC_LIVEUSB_PATH echof "PREPARE > Live USB Building > Mount of ISO file" mount -o loop $ISO $LUC_ISO_PATH echof "PREPARE > Live USB Building > Copy all file from ISO" # 2 errors of symlink will occur, because we can not copy symlink in FAT32 FS rsync -aPv --exclude 'filesystem.squashfs' $LUC_ISO_PATH/ $LUC_LIVEUSB_PATH/ echof "PREPARE > Live USB Building > Copy of squashfs filesystem" rsync -aPv $LUC_ISO_PATH/casper/filesystem.squashfs $LUC_PATH/ # Rename isolinux folder is mandatory because SYSLINUX searches in /syslinux folder (http://www.syslinux.org/wiki/index.php/SYSLINUX#How_do_I_Configure_SYSLINUX.3F) mv $LUC_LIVEUSB_PATH/isolinux/ $LUC_LIVEUSB_PATH/syslinux echof "PREPARE > Live USB Building > Create boot configuration" cat > "$LUC_LIVEUSB_PATH/syslinux/syslinux.cfg" < Live USB Building > Make `echo $DEV`1 bootable" # We must use gfxboot.c32 file's host (https://bugs.launchpad.net/ubuntu/+source/usb-creator/+bug/1325801/comments/11) rsync -aPv /usr/lib/syslinux/gfxboot.c32 $LUC_LIVEUSB_PATH/syslinux/ # Last step to make the USB bootable (`syslinux -i dev` run too) syslinux "$DEV"1 ################################ CUSTOMIZE ################################ echof "=== CUSTOMIZE LIVE USB ===" echof "CUSTOMIZE > Extract SQUASHFS filesystem" mount -t squashfs -o loop $LUC_PATH/filesystem.squashfs $LUC_SQUASHFS_PATH rsync -aPv $LUC_SQUASHFS_PATH/ $LUC_CUSTOM_SQUASHFS_PATH/ echof "CUSTOMIZE > Adding auto-trigger script on reboot" # Entry point to execute an external script and following the execution in a terminal echo sudo lxterminal -t "'"$WAITING_REBOOT_TITLE"'" \ -e "bash -c \"$RUNME1ST_EXT_PATH\" &" \ >> $LUC_CUSTOM_SQUASHFS_PATH/etc/profile # Folder in which we are storing external scripts of live system mkdir $SCRIPTS_PATH echof "CUSTOMIZE > Building off auto triggered script" bash -c "cat > $LUC_LIVEUSB_PATH/$RUNME1ST_ROOT_PATH" < /etc/network/interfaces" <> /home/$ME/.profile" <> /home/$ME/.bashrc" < $RUNMELAST_PATH" < Building of 'reset all' script" bash -c "cat > $LUC_LIVEUSB_PATH/$RESET_ROOT_PATH" < Restore SQUASHFS filesystem" mksquashfs $LUC_CUSTOM_SQUASHFS_PATH \ $LUC_LIVEUSB_PATH/casper/filesystem.squashfs -info ################################ FINALIZE ################################ echof "=== FINALIZE LIVE USB ===" echof "FINALIZE > Unmount and cleaning" umount $LUC_SQUASHFS_PATH umount $LUC_LIVEUSB_PATH umount $LUC_ISO_PATH rm -rf $LUC_PATH echof "~~~ SUCCESS ! YOUR LIVE USB IS READY TO RUN ! ~~~" $C_green unset -f echof