#!/bin/bash # Simona Pisano - 2018-11-27 # simona-scripts # Libertamente utilizzabile sotto GPL v3 if [[ $1 == "-h" || $1 == "--help" ]] ; then cat << EOF macinstall command help Imagine you want install arch linux one time and that clone on all disk ad pc you have. But you should have some different file that differ from one installation to another. This command help you to manage this. Imagine you have your /etc/macinstall.d/yourpc* with all files/folder like: /etc/macinstall.d/yourpc1/etc/fstab /etc/macinstall.d/yourpc1/boot/grug/grub.cfg /etc/macinstall.d/yourpc1/etc/machine-id /etc/macinstall.d/yourpc1/etc/hostname /etc/macinstall.d/yourpc1/etc/ssh/host_* /etc/macinstall.d/yourpc1/.. A second install like /etc/macinstall.d/yourpc2/etc/fstab /etc/macinstall.d/yourpc2/boot/grug/grub.cfg /etc/macinstall.d/yourpc2/etc/machine-id /etc/macinstall.d/yourpc2/etc/hostname /etc/macinstall.d/yourpc2/etc/ssh/host_* /etc/macinstall.d/yourpc2/etc/.. A config file with sessione [yourpc1] and [yourpc2] (edit yourself macinstall.conf) /etc/macinstall.d/macinstall.conf with: [yourpc1] CopyFilesNum=5 CopyFile1=/etc/fstab CopyFile2=/boot/grub/grub.cfg CopyFile3=/etc/grub.d/40_custom CopyFile4=/etc/hostname CopyFile5=/etc/machine-id CopyDirectoriesNum=1 CopyDirectory1=/etc/ssh WriteSemaphore=yes AllowOnlyIfPreviousMacIs=yourpc2 and [yourpc2] CopyFilesNum=5 CopyFile1=/etc/fstab CopyFile2=/boot/grub/grub.cfg CopyFile3=/etc/grub.d/40_custom CopyFile4=/etc/hostname CopyFile5=/etc/machine-id CopyDirectoriesNum=1 CopyDirectory1=/etc/ssh WriteSemaphore=yes AllowOnlyIfPreviousMacIs=yourpc1 And finally a command like to switch from one system to another macinstall yourpc1 ---this-is-not-an-exercise macinstall yourpc2 ---this-is-not-an-exercise And a semaphore file like /etc/macinstall.d/CurrentSystem-yourpc1 or /etc/macinstall.d/CurrentSystem-yourpc2 Summary usage macinstall [-i --info none] [--help|-h] [--version] name-install [local-import] Option parameters --help -h -> this help page -i --info or blank -> who am i looking semaphore file --version -> output version information and exit -y --ask-confirm -> ask confirm before proceeed ---this-is-not-an-exercise -> force real work. without this none is really done. this is a secure check. ---no-test -> use dest / instead $USER/test Path used /etc/macinstall.d -> contains all single install related files (example fstab grub.cfg machine-id...) /usr/bin/macinstall -> this command itself /etc/macinstall-d/CurrentSystem-pcname -> semaphore of installed system (touch bank file) Example A file /etc/macinstall.d/macinstall.conf with some demo config is already supplyed. Packages required sed sudo Cfg file used /etc/macinstall.d/macinstall.conf EOF exit 0 elseif [[ $1 == "--version" ]] echo "macinstall Version 0.0" exit 0 fi # ## who am I # path_prefix_system_semaphore="/etc/macinstall.d/CurrentSystem-" #path_prefix_system_semaphore="/home/simona/My Work/my-pkg simonascripts/root-test/etc/CurrentSystem-" if [[ $1 == "" || $1 == "-i" || $1 == "--info" ]] ; then numSem=`ls "$path_prefix_system_semaphore"* 2> /dev/null | wc -l` case $numSem in 1) currSystem=`ls -1 "$path_prefix_system_semaphore"* 2> /dev/null` currSystem="${currSystem:${#path_prefix_system_semaphore}:${#currSystem}-${#path_prefix_system_semaphore}}" echo "I am $currSystem" ;; 0) echo "Can't detect current system." ;; *) echo "Ambiguous CurrentSystem ($numSem)!!!" ;; esac fi [[ ! -r /bin/sed ]] && { echo -e "$ERR Missing sed utility! Exit"; exit 1; } [[ ! -r /bin/sudo ]] && { echo -e "$ERR Missing sudo utility! Exit"; exit 1; } [[ $1 != "" ]] && install_macname=$1 || exit 0 #[[ $1 != "" ]] && install_macname=$1 || { echo "Please insert install name as first command parameter!!"; exit 0; } runLocalImport=false [[ $2 == "local-import" ]] && runLocalImport=true flagNoTest=false flagForceRealWork=false flagAskConfirm=false while [ $# -ne 0 ] ; do case $1 in -y|--ask-confirm) flagAskConfirm=true ;; ---this-is-not-an-exercise) flagForceRealWork=true;; ---no-test) flagNoTest=true;; *) ;; esac shift done #color Foreground Background #black 30 40 #red 31 41 #green 32 42 #yellow 33 43 #blue 34 44 #magenta 35 45 #cyan 36 46 #white 37 47 EchoReset="\e[0m" echo -e -n "$EchoReset" OK="\E[32;40m[OK]${EchoReset}" WARN="\E[33;40m[WARN]${EchoReset}" ERR="\E[31;40m[ERR]${EchoReset}" #echo -e "$OK $WARN $ERR" #path_cfg must be '/' terminated filename_cfg="macinstall.conf" path_cfg="/etc/macinstall.d/" [[ ${path_cfg:${#path_cfg}-1:1} != "/" ]] && path_cfg="$path_cfg/" #if last char is not '/' add it if [[ ! -d $path_cfg ]] ; then mkdir -p $path_cfg [[ $? -ne 0 ]] && { echo -e "$ERR Fail '$path_cfg' mkdir cmd creation !!"; exit 1; } fi if [[ ! -r $path_cfg$filename_cfg ]] ; then touch $path_cfg$filename_cfg [[ $? -ne 0 ]] && { echo -e "$ERR Fail '$path_cfg$filename_cfg' touch cmd creation !!"; exit 1; } fi #path_dest must be '/' terminated path_dest="$HOME/test/" [[ "$flagNoTest" == true ]] && { echo "$WARN Using real path / for destination..."; path_dest="/"; } [[ ${path_dest:${#path_dest}-1:1} != "/" ]] && path_dest="$path_dest/" #if last char is not '/' add it if [[ ! -d $path_dest ]] ; then [[ ${path_dest:0:5} == "/home" && ! -d "/home" ]] && { echo "$ERR Path '/home' missing. (For / use) Exit."; exit 1; } mkdir -p $path_dest [[ $? -ne 0 ]] && { echo -e "$ERR Fail $path_dest mkdir cmd creation !!"; exit 1; } fi postfix_bak_file_name=".bak" #cfg related prop_cfg_file_copy_num="CopyFilesNum" prop_cfg_dir_copy_num="CopyDirectoriesNum" prop_cfg_rm_num="RmNum" prop_cfg_file_copy="CopyFile" prop_cfg_dir_copy="CopyDirectory" prop_cfg_rm="Rm" prop_cfg_write_sem="WriteSemaphore" prop_cfg_read_sem="AllowOnlyIfPreviousMacIs" if [[ "$flagAskConfirm" == true ]] ; then echo -n "Continue? (Y/N): "; read ask [[ ! $ask =~ ^(yes|y|YES|y|s|S|si|SI|sì)$ ]] && { echo "Exit forced by user."; exit 0; } fi number_files=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_file_copy_num[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` number_directories=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_dir_copy_num[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` number_rm=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_rm_num[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` ok_write_semaphore=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_write_sem[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` [[ $ok_write_semaphore == "" ]] && ok_write_semaphore="yes" #default [[ $ok_write_semaphore != "yes" && $ok_write_semaphore != "no" ]] && ok_write_semaphore="yes" #default #Check cfg file integrity if [[ $number_files -lt 1 && $number_directories -lt 1 && $number_rm -lt 1 ]] ; then echo -e "$ERR $filename_cfg: None to do!!! 'CopyFilesNum' or 'CopyDirectoriesNum' or 'RmNum' not correctly defined. Please modify cfg." exit 1 fi if [[ $number_files -gt 0 ]] ; then for (( counter=1; counter <= $number_files; counter++ )) ; do dupe=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_file_copy$counter[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` [[ $dupe == "" ]] && { echo -e "$ERR $filename_cfg: '$prop_cfg_file_copy$counter' not found inside cfg. Fix cfg!!"; exit 1; } [[ ! -r $path_cfg$install_macname$dupe ]] && { echo -e "$ERR File '$path_cfg$install_macname$dupe' defined in config but not found!"; exit 1; } #prepare destination creatinf directory if required #remove starting '/' if exist [[ ${dupe:0:1} == "/" ]] && dupe=${dupe:1:${#dupe}-1} # extract path from $dupe and mkdir -p it dupeFilename=${dupe##*/} #extract froms tring all is over last '/' (filename) dupePath=${dupe:0:${#dupe}-${#dupeFilename}} #extract path (remove filename cutting string) #echo "filename=$dupeFilename path=$path_dest$dupePath" #debug if [[ ! -d "$path_dest$dupePath" ]] ; then mkdir -p "$path_dest$dupePath" if [[ $? -ne 0 ]] ; then sudo mkdir -p "$path_dest$dupePath" [[ $? -ne 0 ]] && { echo -e "$WARN Fail generating directory '$path_dest$dupePath'. Exit."; exit 1; } fi fi done fi if [[ $number_directories -gt 0 ]] ; then for (( counter=1; counter <= $number_directories; counter++ )) ; do dupe=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_dir_copy$counter[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` [[ $dupe == "" ]] && { echo -e "$ERR $filename_cfg: '$prop_cfg_dir_copy$counter' not found inside cfg. Fix cfg!!"; exit 1; } [[ ! -d $path_cfg$install_macname$dupe ]] && { echo -e "$ERR Directory '$path_cfg$install_macname$dupe' defined in config but not found!"; exit 1; } #prepare destination creating directory if required #remove starting '/' if exist [[ ${dupe:0:1} == "/" ]] && dupe=${dupe:1:${#dupe}-1} #remove ending '/' if exist [[ ${dupe:${#dupe}-1:1} == "/" ]] && dupe=${dupe:0:${#dupe}-1} # extract path from $dupe and mkdir -p it dupeFoldername=${dupe##*/} #extract froms tring all is over last '/' (foldername) dupePath=${dupe:0:${#dupe}-${#dupeFoldername}} #extract path (remove filename cutting string) if [[ ! -d "$path_dest$dupePath" ]] ; then mkdir -p "$path_dest$dupePath" if [[ $? -ne 0 ]] ; then sudo mkdir -p "$path_dest$dupePath" [[ $? -ne 0 ]] && { echo -e "$WARN Fail generating directory '$path_dest$dupePath'. Exit."; exit 1; } fi fi done fi if [[ $number_rm -gt 0 ]] ; then for (( counter=1; counter <= $number_rm; counter++ )) ; do dupe=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_rm$counter[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` [[ $dupe == "" ]] && { echo -e "$ERR $filename_cfg: '$prop_cfg_rm$counter' not found inside cfg. Fix cfg!!"; exit 1; } [[ ! -d $path_cfg$install_macname$dupe ]] && { echo -e "$ERR File/dir '$path_cfg$install_macname$dupe' defined in config but not found!"; exit 1; } done fi # ------------------------------------------------------------------------------------------------------------------------ # WORK ------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------------ if [[ "$flagForceRealWork" == true ]] ; then echo -e "$WARN Warning: using REAL path. This is not a simulation. I can damage system." echo "Dest dir used is '$path_dest'." echo -n "Continue? (Y/N): "; read ask [[ ! $ask =~ ^(yes|y|YES|y|s|S|si|SI|sì)$ ]] && { echo "Exit forced by user."; exit 0; } fi #TO-DO local-import come secondo parametro #legge macchina corrente su file semaforo, legge macchina corrente da parametro (devono corrispondere) # e va ricopiarsi tutti i files elencati sulla macchina (se presente) nella cartella giusta (è un fresh dei files di install) if [[ $runLocalImport == true ]] ; then #if current install exist but it is not the one current i can't proceede numSem=$(ls "$path_prefix_system_semaphore"* 2> /dev/null | wc -l) if [[ numSem -gt 0 ]] ; then if [[ ! -r "$path_prefix_system_semaphore$install_macname" ]] ; then echo -e "$ERR Another install. Can't work" exit 1 fi fi # exit 0 fi #????? #echo "1" #sed -nr "/^\[$install_macname\]/ { :l /^ciccia[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg #sed -nr "/^\[$install_macname\]/ { :l /^AllowOnlyIfPreviousMacIs[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg # ## Verify semaphore file (opzional) # AllowOnlyIfPreviousMacIs=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_read_sem[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` if [[ $AllowOnlyIfPreviousMacIs != "" ]] ; then echo " Found in cfg: AllowOnlyIfPreviousMacIs=$AllowOnlyIfPreviousMacIs" if [[ ! -r "$path_prefix_system_semaphore$AllowOnlyIfPreviousMacIs" ]] ; then echo -e "$ERR Missing semaphore '$path_prefix_system_semaphore$AllowOnlyIfPreviousMacIs'. Previous install required but not verified. Stop." exit 1 else flag_old_mac_to_erase="$AllowOnlyIfPreviousMacIs" fi else echo -e "$WARN Warning: control of previous installed machine disabled." echo -n "Continue? (Y/N): "; read ask [[ ! $ask =~ ^(yes|y|YES|y|s|S|si|SI|sì)$ ]] && { echo "Exit forced by user."; exit 0; } fi # ## Backup old files # if [[ $number_files -gt 0 ]] ; then for (( counter=1; counter <= $number_files; counter++ )) ; do backup=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_file_copy$counter[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` [[ ${backup:0:1} == "/" ]] && backup=${backup:1:${#backup}-1} #remove starting '/' if exist if [[ -r $path_dest$backup ]] ; then if [[ "$flagForceRealWork" == true ]] ; then cp -f "$path_dest$backup" "$path_dest$backup$postfix_bak_file_name" if [[ $? -ne 0 ]] ; then sudo cp -f "$path_dest$backup" "$path_dest$backup$postfix_bak_file_name" if [[ $? -ne 0 ]] ; then echo -e "$WARN Fail generating backup file '$path_dest$backup$postfix_bak_file_name'. Ask User." echo -n "Continue? (Y/N): "; read ask [[ ! $ask =~ ^(yes|y|YES|y|s|S|si|SI|sì)$ ]] && { echo "Exit forced by user with error."; exit 1; } else echo -e "$OK Generation of backup file [1] '$path_dest$backup' as '$path_dest$backup$postfix_bak_file_name'" fi else echo -e "$OK Generation of backup file [2] '$path_dest$backup' as '$path_dest$backup$postfix_bak_file_name'" fi else echo -e "$OK [Simulated] Generation of backup file '$path_dest$backup' as '$path_dest$backup$postfix_bak_file_name'" fi else echo -e "$WARN File '$path_dest$backup' to backup not present. Ignoring backup." fi done fi if [[ $number_directories -gt 0 ]] ; then for (( counter=1; counter <= $number_directories; counter++ )) ; do backup=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_dir_copy$counter[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` [[ ${backup:0:1} == "/" ]] && backup=${backup:1:${#backup}-1} #remove starting '/' if exist if [[ -d "$path_dest$backup" ]] ; then if [[ "$flagForceRealWork" == true ]] ; then #if bak directory alrrady exist to not create a new ssh dir inside it.... if [[ -d "$path_dest$backup$postfix_bak_file_name" ]] ; then rm -r -f "$path_dest$backup$postfix_bak_file_name" if [[ $? -ne 0 ]] ; then sudo rm -r -f "$path_dest$backup$postfix_bak_file_name" [[ $? -ne 0 ]] && echo -e "$WARN Fail removing old backup directory.'$path_dest$backup$postfix_bak_file_name'." fi fi #do work mv -f "$path_dest$backup" "$path_dest$backup$postfix_bak_file_name" if [[ $? -ne 0 ]] ; then sudo mv -f "$path_dest$backup" "$path_dest$backup$postfix_bak_file_name" if [[ $? -ne 0 ]] ; then echo -e "$WARN Fail generating backup directory '$path_dest$backup$postfix_bak_file_name'. Ask User." echo -n "Continue? (Y/N): "; read ask [[ ! $ask =~ ^(yes|y|YES|y|s|S|si|SI|sì)$ ]] && { echo "Exit forced by user with error."; exit 1; } else echo -e "$OK Generation [1] of backup directory '$path_dest$backup$postfix_bak_file_name'" fi else echo -e "$OK Generation [2] of backup directory '$path_dest$backup$postfix_bak_file_name'" fi else echo -e "$OK [Simulated] Generation of backup directory '$path_dest$backup$postfix_bak_file_name'" fi else echo -e "$WARN Directory '$path_dest$backup' to backup not present. Ignoring backup." fi done fi if [[ $number_rm -gt 0 ]] ; then echo -e "$WARN Attention! Backup of remove ($number_rm) not done." fi # ## Copia nuovi files # if [[ $number_files -gt 0 ]] ; then for (( counter=1; counter <= $number_files; counter++ )) ; do dupe=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_file_copy$counter[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` [[ ${dupe:0:1} == "/" ]] && dupe=${dupe:1:${#dupe}-1} #remove starting '/' if exist if [[ "$flagForceRealWork" == true ]] ; then cp -f "$path_cfg$install_macname/$dupe" "$path_dest$dupe" if [[ $? -ne 0 ]] ; then sudo cp -f "$path_cfg$install_macname/$dupe" "$path_dest$dupe" if [[ $? -ne 0 ]] ; then echo -e "$ERR Fail copyng file over destination from <$install_macname> to '$path_dest$dupe'. Ask User." echo -n "Continue? (Y/N): "; read ask [[ ! $ask =~ ^(yes|y|YES|y|s|S|si|SI|sì)$ ]] && { echo "Exit forced by user with error."; exit 1; } fi fi echo -e "$OK Copied file from <$install_macname> '$path_dest$dupe'." else echo -e "$OK [Simulated] Copied file from '$path_cfg$install_macname/$dupe' to '$path_dest$dupe'." fi done fi if [[ $number_directories -gt 0 ]] ; then for (( counter=1; counter <= $number_directories; counter++ )) ; do dupe=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_dir_copy$counter[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` [[ ${dupe:0:1} == "/" ]] && dupe=${dupe:1:${#dupe}-1} #remove starting '/' if exist [[ ${dupe:${#dupe}-1:1} == "/" ]] && dupe=${dupe:0:${#dupe}-1} #remove ending '/' if exist if [[ "$flagForceRealWork" == true ]] ; then cp -f -r "$path_cfg$install_macname/$dupe" "$path_dest$dupe" if [[ $? -ne 0 ]] ; then sudo cp -f -r "$path_cfg$install_macname/$dupe" "$path_dest$dupe" if [[ $? -ne 0 ]] ; then echo -e "$ERR Fail copyng directory over destination from <$install_macname> to '$path_dest$dupe'. Ask User." echo -n "Continue? (Y/N): "; read ask [[ ! $ask =~ ^(yes|y|YES|y|s|S|si|SI|sì)$ ]] && { echo "Exit forced by user with error."; exit 1; } fi fi echo -e "$OK Copied directory <$install_macname> '$path_dest$dupe'." else echo -e "$OK [Simulated] Copied directory from '$path_cfg$install_macname/$dupe' to '$path_dest$dupe'." fi done fi if [[ $number_rm -gt 0 ]] ; then for (( counter=1; counter <= $number_rm; counter++ )) ; do dupe=`sed -nr "/^\[$install_macname\]/ { :l /^$prop_cfg_rm$counter[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" $path_cfg$filename_cfg` [[ ${dupe:0:1} == "/" ]] && dupe=${dupe:1:${#dupe}-1} #remove starting '/' if exist if [[ "$flagForceRealWork" == true ]] ; then rm -f "$path_dest$dupe" if [[ $? -ne 0 ]] ; then sudo rm -f "$path_dest$dupe" if [[ $? -ne 0 ]] ; then echo -e "$ERR Fail removing file '$path_dest$dupe'. Ask User." echo -n "Continue? (Y/N): "; read ask [[ ! $ask =~ ^(yes|y|YES|y|s|S|si|SI|sì)$ ]] && { echo "Exit forced by user with error."; exit 1; } fi fi echo -e "$OK Removed file <$install_macname> '$path_dest$dupe'." else echo -e "$OK [Simulated] Removed file '$path_dest$dupe'." fi done fi # ## Write new semaphore (can be disabled) # if [[ $ok_write_semaphore == "yes" ]] ; then if [[ -r $path_prefix_system_semaphore$flag_old_mac_to_erase ]] ; then #if [[ "$flagForceRealWork" == true ]] ; then rm "$path_prefix_system_semaphore$flag_old_mac_to_erase" if [[ $? -ne 0 ]] ; then sudo rm "$path_prefix_system_semaphore$flag_old_mac_to_erase" [[ $? -ne 0 ]] && echo -e "$WARN All was OK but I can't remove '$path_prefix_system_semaphore$flag_old_mac_to_erase' !!" fi touch "$path_prefix_system_semaphore$install_macname" if [[ $? -ne 0 ]] ; then sudo touch "$path_prefix_system_semaphore$install_macname" [[ $? -ne 0 ]] && echo -e "$WARN All OK EXCEPT creation of blank file '$path_prefix_system_semaphore$install_macname' !!" fi fi fi exit 0;