ghostwolf59
Contributor
- Joined
- Mar 2, 2013
- Messages
- 165
Have this weird thing happening - the bash script I created works perfect via the web interface - the bash used then is /usr/local/bin/bash
Then tried to run the same script from of a the shell on my nas - when executing the same script I get "Missing }."
Figured that there's a different bash when open a shell on nas. and sure enough - the bash shell now is /bin/bash
Updated the script to point to this, but the same "Missing }." is thrown. Any idea why this happens...?
Also wonder how I can get this script onto my thumb drive so it's always available - as it stands now I copied it to one of my mounted volumes (which is silly)
here's the complete script as it stands (supports rsync as well as zfs snapshot backup/restore)
Then tried to run the same script from of a the shell on my nas - when executing the same script I get "Missing }."
Figured that there's a different bash when open a shell on nas. and sure enough - the bash shell now is /bin/bash
Updated the script to point to this, but the same "Missing }." is thrown. Any idea why this happens...?
Also wonder how I can get this script onto my thumb drive so it's always available - as it stands now I copied it to one of my mounted volumes (which is silly)
here's the complete script as it stands (supports rsync as well as zfs snapshot backup/restore)
Code:
#/usr/local/bin/bash # # backup/restore syncronization # # https://forums.freenas.org/index.php?threads/zfs-send-to-external-backup-drive.17850/ #echo "Starting" req="${1,,}" #convert to lower case request (backup or restore) drive="${2^^}" #convert to upper case target/destination drive dt="${3^^}" #convert to upper case date of a backup point to resore from force="${3,,}" #convert flag setting ty lower case u="" #default force setting flag (rsync) if [ "${force}" == "" ]; then force="" fi back="BACKUP" #default name of backup volume status=0 # run if user hits control-c function control_c() { echo -en "\n*** Ouch! Exiting ***\n" exit $? } # trap keyboard interrupt (control-c) trap control_c SIGINT #pause prompt function pause(){ read -p "$*" } #command line syntax error message function error() { echo "command line error ${@}" echo " to backup zfs with snapshots:" echo " /mnt/<drive>/backrest.sh backup <drive>" echo " or to restore zfs with snapshots:" echo " /mnt/<drive>/backrest.sh restore <drive> <ccyymmdd> or sync <drive>" echo " or to do rsync do ..." echo " backup drive to /mnt/${back}:" echo " /mnt/<drive>/backrest.sh sync <drive>" echo " restore from /mnt/${back}:" echo " /mnt/<drive>/backrest.sh syncrestore <drive>" return } #check if the drive is mounted or even exists on the system function is_mounted() { local FS=$(zfs get -H mounted "${@}") FS_REGEX="^${@}\s+mounted\s+yes\s+-" #check for errors if [ "${FS}" == "" ]; then status=$? #status from last function call echo "${@} not found/mounted" return 0 #evaluates to false - error condition fi if [[ $FS =~ $FS_REGEX ]]; then status=$? #status from last function call echo "${@} not mounted" return 0 #evaluates to false - error condition fi #drive checked out ok echo "${@} mounted" return 1 #evaluates to true - success } #wrapper to ensure BACKUP drive and nominated target/destination drive is mounted/exists function checkMountPoints() { #checks if the backup/restore drive exists #check source drive is_mounted ${@} status=$? #status from last function call if [ $status == 1 ]; then echo "${@} checked out ok" else return 0 #evalutes to false error condition fi #check backup drive is_mounted ${back} status=$? #status from last function call if [ $status == 1 ]; then echo "${back} checked out ok" return 1 else return 0 #evaluates to false - error condition fi } #rsync across the whole source volume to backup destination volume function RyncFromSourceToDetachedMediaBackup() { #checkMountPoints ${drive} checkMountPoints ${1} status=$? #status from last function call if [ $status == 1 ]; then echo "rsync -pogavt${2} /mnt/${1} /mnt/${back}" rsync -pogavt${2} /mnt/${1} /mnt/${back} status=$? #status from last function call if [ $status == 0 ]; then echo "rsync from /mnt/${1} to /mnt/${back}/${1} successful" else echo "rsync from /mnt/${1} to /mnt/${back}/${1} unsuccessful" fi else status=1 fi return $status } #rsync across the whole backup volume to destination source volumne function RsyncFromBackupToSourceRestore() { #checkMountPoints ${drive} checkMountPoints ${1} status=$? #status from last function call if [ $status == 1 ]; then echo "rsync -pogavt${2} /mnt/${back}/${1}/ /mnt/${1}" rsync -pogavt${2} /mnt/${back}/${1}/ /mnt/${1} status=$? #status from last function call if [ $status == 0 ]; then echo "rsync from /mnt/${back}/${1}/ to /mnt/${1} successful" else echo "rsync from /mnt/${back}/${1}/ to /mnt/${1} unsuccessful" fi else status=1 fi return $status } function takesnapshot() { #echo "start takesnapshot() of ${@} as ${@}-$(date +%Y%m%d)" zfs snapshot -r ${@}@${@}-$(date +%Y%m%d) status=$? #status from last function call if [ $status == 0 ]; then status=1 else status=0 fi #echo "chk outcome takesnapshot() $status" return $status } function renamesnapshot() { #echo "start renamesnapshot() ${@}@${@}-${date} to ${@}@${@}-$(date +%Y%m%d)-restored_$(date +%Y%m%d)" zfs rename -r ${@}@${@}-${date} ${@}@${@}-$(date +%Y%m%d)-restored_$(date +%Y%m%d) status=$? #status from last function call if [ $status == 0 ]; then status=1 else status=0 fi #echo "chk outcome renamesnapshot() $status" return $status } function deletesnapshot() { #echo "start deletesnapshot() ${@}@${@}-$(date +%Y%m%d)" zfs destroy -r ${@}@${@}-$(date +%Y%m%d) status=$? #status from last function call if [ $status == 0 ]; then status=1 else status=0 fi #echo "chk outcome deletesnapshot() $status" return $status } function sendsnapshot () { #echo "start sendsnapshot() ${@}@${@}-$(date +%Y%m%d) to ${back}/${@}-$(date +%Y%m%d)" zfs send -R ${@}@${@}-$(date +%Y%m%d) | zfs receive -vF ${back}/${@}-$(date +%Y%m%d) status=$? #status from last function call if [ $status == 0 ]; then status=1 else status=0 fi #echo "chk outcome sendsnapshot() $status" return $status } #takes the backup of nominated drive, sending it to the BACKUP drive function doBackup() { checkMountPoints ${drive} status=$? #status from last function call if [ $status == 1 ]; then echo "about to take snapshot of $drive" takesnapshot $drive status=$? #status from last function call if [ $status == 1 ]; then echo "about to send snapshot of $drive to $back" sendsnapshot ${drive} status=$? #status from last function call if [ $status == 1 ]; then echo "about to take snapshot of ${back}" takesnapshot ${back}; status=$? #status from last function call if [ $status == 1 ]; then echo "about to delete snapshot of ${drive}" deletesnapshot ${drive} status=$? #status from last function call if [ $status == 1 ]; then #echo "about to delete snapshot of ${back}" #deletesnapshot ${back} #status=$? #status from last function call #if [ $status == 1 ]; #then echo "Successfully backed up ${drive} onto ${back}" return #fi fi fi fi fi fi status=$? #status from last function call error $status echo "Unsuccessful backup of ${@}" return } function validateDate() { # Script expecting a Date parameter in YYYYMMDD format as input echo ${dt} | grep '^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$' status=$? #status from last function call if [ $status -eq 0 ]; #valid date then status=0 #do nothing statement else #since previous test failed I will try to reverse the argument assuming a reverce input echo ${drive} | grep '^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$' status=$? #status from last function call if [ $status -eq 0 ]; #valid date then # parameters in reversed argument order - switching order tmpdrive="${dt}" dt="${drive}" drive="${tmpdrive}" fi fi return $status #0=success, otherwise error } #some checks post restore a zfs volume and all datasets function doRestore() { echo "Start Restore..." validateDate status=$? #status from last function call #validated date params if [ $status == 0 ]; then checkMountPoints ${drive} #check if nominated target/destination drive/volume is mounted/available status=$? #status from last function call if [ $status == 1 ]; #target/destination drives(volumes) accessible then echo "Initiate restore of $drive from ${back}@${drive}-${dt}" execRestore ${drive} ${dt} #do the restore of drive for date (assuming it exists for set date) status=$? #status from last function call if [ $status == 0 ]; #success then echo "Successfully restored $drive from ${back}@${drive}-${dt}" else echo "Unsuccessful restore of $drive from ${back}" error $status fi else echo "${drive} or ${back} not mounted" error $status fi else echo "${dt} is not a valid date" error $status fi return } function destroyDataset () { echo "about to delete dataset ${@}" if [ "${@}" == "" ]; then echo "empty dataset passed" status=1 else #zfs destroy -R $back/$drive-$dt/${@} zfs destroy -R ${@} status=$? #status from last function call if [ $status == 0 ]; #successful rename then #echo "Successfully deleted dataset $back/$drive-$dt/${@}" echo "Successfully deleted dataset ${@}" else #echo "Faailed to delete dataset $back/$drive-$dt/${@}" echo "Failed to delete dataset ${@}" fi fi return $status } function jailCleanExists () { echo "check if ${@} exists" zfs list ${@} status=$? #status from last function call if [ $status == 0 ]; #successful rename then status=1 else status=0 fi echo "status from call $status" return $status } function removeJailDependencies () { exception=0 jailCleanExists ${@}/jails/sickbeard_2 status=$? #status from last function call if [ $status == 1 ]; then destroyDataset ${@}/jails/sickbeard_2 status=$? #status from last function call if [ $status == 0 ]; then echo "successfully removed ${@}/jails/jails/sickbeard_2" else echo "Warning: ${@}/jails/jails/sickbeard_2 not found" exception=1 fi fi jailCleanExists ${@}/jails/plexmediaserver_1 status=$? #status from last function call if [ $status == 1 ]; then destroyDataset ${@}/jails/plexmediaserver_1 status=$? #status from last function call if [ $status == 0 ]; then echo "successfully removed ${@}/jails/plexmediaserver_1" else echo "Warning: ${@}/jails/plexmediaserver_1 not found" exception=1 fi fi jailCleanExists ${@}/jails/firefly_1 status=$? #status from last function call if [ $status == 1 ]; then destroyDataset ${@}/jails/firefly_1 status=$? #status from last function call if [ $status == 0 ]; then echo "successfully removed ${@}/jails/firefly_1" else echo "Warning: ${@}/jails/firefly_1 not found" exception=1 fi fi jailCleanExists ${@}/jails/.warden-template-pluginjail@clean status=$? #status from last function call if [ $status == 1 ]; then destroyDataset ${@}/jails/.warden-template-pluginjail@clean status=$? #status from last function call if [ $status == 0 ]; then echo "successfully removed ${@}/jails/.warden-template-pluginjail@clean" else echo "Warning: ${@}/jails/.warden-template-pluginjail@clean not found" exception=1 fi fi status=$exception return $status } #restore a zfs volume and all datasets function execRestore(){ #echo "Restoring ${drive} for ${dt} from ${back}/${drive}-${dt}..." #test echo "Restoring ${back}@${drive}-${dt} to ${drive}..." #assume the backup for set date exists - the backup name is based on previous backup whith inherited source volume name zfs send -R ${back}@${drive}-${dt} | zfs receive -vF ${drive}/ status=$? #status from last function call if [ $status == 0 ]; #worked then #take a new snapshot from restored data takesnapshot ${drive} status=$? #status from last function call if [ $status == 0 ]; #snapshot successful then renamesnapshot ${drive} #rename previous snaphot on the destination volume to prevent accidental restore since the backup release superseeds this snapshot status=$? #status from last function call if [ $status == 0 ]; #successful rename then echo "about to delete snapshot of ${back}" deletesnapshot ${back} #remove the snapshot from the backup drive since it's now been restored (not sure this is the correct approach) status=$? #status from last function call if [ $status == 0 ]; #successful rename then echo "about to delete dataset ${back}@${drive}-${dt}" destroyDataset ${back}@${drive}-${dt} status=$? #status from last function call if [ $status == 0 ]; #successful rename then echo "check if ${drive}/jails/.warden-template-pluginjail@clean exists" jailCleanExists ${drive}/jails/.warden-template-pluginjail@clean status=$? #status from last function call if [ $status == 1 ]; #@clean exists then echo "remove dependencies for ${back}/${drive}-${dt}/jails/.warden-template-pluginjail@clean" removeJailDependencies ${back}/${drive}-${dt} status=$? #status from last function call if [ $status == 0 ]; #@cleaned then echo "Dependencies successfully removed for ${back}/${drive}-${dt}/jails/.warden-template-pluginjail@clean" status=1 else echo "Exception thrown while cleaning up dependant datasets for ${back}/${drive}-${dt}/jails/.warden-template-pluginjail@clean" status=0 fi else status=1 fi else status=0 fi fi fi fi fi return $status #status from last call resurned (0=error, 1=success) } #main logic (backup or restore) if [ "${drive}" == "" ]; then error else if [ "${req}" == "backup" ]; then doBackup $drive else if [ "${req}" == "restore" ]; then doRestore $drive $dt else if [ "${req}" == "sync" ]; then if [ "${force}" == "-f" ]; then u="u" fi echo "WARNING: You are about to rsync /mnt/${drive} onto /mnt/${back}" pause "Press [Enter]key to continue or CTRL+C to cancel" RyncFromSourceToDetachedMediaBackup ${drive} ${u} status=$? #status from last function call if [ $status == 0 ]; #successful rename then echo "ok" else error fi else if [ "${req}" == "syncrestore" ]; then if [ "${force}" == "-f" ]; then u="u" fi echo "WARNING: You are about to rsync /mnt/${back}/${drive}/ onto /mnt/${drive}" pause "Press [Enter]key to continue or CTRL+C to cancel" RsyncFromBackupToSourceRestore ${drive} ${u} status=$? #status from last function call if [ $status == 0 ]; #successful rename then echo "ok" else error fi else error fi fi fi fi fi exit 0 #
Last edited: