Register
It is currently Fri Oct 24, 2014 6:00 am

Backup script needs refinement


All times are UTC - 6 hours


Post new topic Reply to topic  [ 4 posts ] 
Author Message
 PostPosted: Sun Nov 01, 2009 9:48 am   
User avatar

Joined: Sun Nov 01, 2009 8:59 am
Posts: 25
Location: Try to guess!
Hi, it's with great humbleness that i present my first "serious" attempt at bash scripting: it's basically my personal backup script which compresses and encrypts some folders in a single 7z archive then prompts to send it to a SMB server and\or removable media. It's fully working and i'm here cause i'm afraid my C\C++ and Java background somewhat polluted my bash code; therefore i'd like someone to review my code and point me out the right approach to bash scripting.

Things i don't like in my script:
- directories to backup are hard-coded cause i couldn't figure out a good way to choose them "at runtime";
- filenames: at first i thought hard-coding the file extension would be a good idea, now i'm not so sure;
- paths: is there some kind of standard, a convention maybe?

Wishlist:
- assisted directory entering (autocompletion, that TAB thing you know);
- SMB password acceptance & successful mounting check;

Code:
#!/bin/bash

###############################################################
#BACKUP SCRIPT by e633
#DEPENDENCIES: p7zip, smbfs, md5sum
###############################################################

#Functions definition
function recopy
{
   echo "Re-copying..."
   cp /home/$USER/backupper/$filename.7z $pathh
}

function retransfer
{
   echo "Re-transferring backup file..."
   cp /home/$USER/backupper/$filename.7z /mnt/xbackupper/
}

function cp_to_removable
{
   echo "Copying to specified directory..."
   cp /home/$USER/backupper/$filename.7z $pathh

   echo "Checking MD5 checksum..."   
   dirsum=`md5sum $pathh/$filename.7z`
   dirsum=${dirsum:0:32}
   
   if [ "$dirsum" != "$rightsum" ]; then
      echo "FILE CORRUPTED DURING COPY TO DIRECTORY"
      while [ "$dirsum" != "$rightsum" ]; do
               read -p "Copy again? (y/n) " retry
               if [ $retry == "y" ]; then
               recopy
               fi   
         dirsum=`md5sum /home/$USER/backupper/$filename.7z`
         dirsum=${rightsum:0:32}
      done
   fi
   echo "Done copying to removable media."
}

function cp_to_server
{
   read -p "Enter SMB path. Example: //[IP address]/dir " smbpath
   read -p "Enter SMB username: " smbusr

   stty -echo
   read -p "Enter SMB password: " smbpwd; echo
   stty echo

   echo "Copying to backup server via SAMBA..."
   sudo mkdir /mnt/xbackupper
   sudo mount -t smbfs -o username=$smbusr,password=$smbpwd $smbpath /mnt/xbackupper
   sudo cp /home/$USER/backupper/$filename.7z /mnt/xbackupper/

   echo "Checking md5sum..."
   serversum=`md5sum /mnt/xbackupper/$filename.7z`
   serversum=${serversum:0:32}
   if [ "$serversum" != "$rightsum" ]; then
      echo "FILE CORRUPTED DURING COPY TO SERVER"
      while [ "$serversum" != "$rightsum" ]; do
           read -p "Attempt to re-transfer? (y/n) " retry
         if [ retry == "y" ]; then
         retransfer
         fi
        serversum=`md5sum /mnt/xbackupper/$filename.7z`
      serversum=${serversum:0:32}
       done
   fi
   sudo umount /mnt/xbackupper
   sudo rmdir /mnt/xbackupper
   echo "Done copying to server."
}

#Check that no program is running
read -p "CLOSE ALL PROGRAMS BEFORE PROCEEDING (y/n) " ans
if [ $ans == "y" ]; then
echo "Backup process continuing..." && sleep 1
else echo "BACKUP ABORTED."
exit
fi

mkdir /home/$USER/backupper # Where archives are stored

################################################################
#(compression stage) Create an archive for each directory.
# SAMPLE LINE:
# 7z a /home/myuser/backupper/Documents.7z /home/myuser/Documents -mx=9 -ms=on -mmt=on -mtc=on
# explanation: 7z add [output file.7z] [dir to backup] [suggested options, see /usr/share/doc/p7zip/DOCS/MANUAL/index.htm]
################################################################
echo "Compression stage, this will take long..." && sleep 3
#---------------------------- insert directories to backup below, line by line (see example) ----------------------------


################################################################
#(verification stage) Time to check the archives from the compression stage above. Remember to verify ALL the output files above!
# SAMPLE LINE:
#7z t /home/myuser/backupper/Documents.7z -mmt=on
# Explanation: 7z test [file.7z] [options]; instruction "&& sleep 3" gives time to read the outcome of each test.
################################################################
echo "Testing archives, this will take long..." && sleep 3
#---------------------------- insert archives to test below, line by line (see example) ----------------------------


#Check for errors
read -p "All archive tests successful? (y/n) " ans
if [ $ans == "y" ]; then
echo "Backup process continuing..."
else echo "BACKUP ABORTED, FILES NOT DELETED. CHECK /home/$USER/backupper."
exit
fi

#(encryption stage) Encrypting in one single archive (no more compression)
echo "Encryption stage, this will take long..."
stty -echo
read -p "Insert archive password (and remember it): " archpwd; echo
stty echo
filename="$USER@$HOSTNAME-backup_`date +%Y-%m-%0e`"
7z a /home/$USER/backupper/$filename.7z /home/$USER/backupper/*.7z -mx=0 -mmt=on -ms=on -p$archpwd -mhe

filesize=$(stat -c%s "/home/$USER/backupper/$filename.7z")
echo "Final size of file $filename is $filesize bytes."

read -p "Would you like to rename the backup file? (y/n) " ans
if [ $ans == "y" ]; then
read -p "Enter new filename: (NO EXTENSION)" newfilename
mv /home/$USER/backupper/$filename.7z /home/$USER/backupper/$newfilename.7z
filename=$newfilename
fi

echo "Saving MD5 checksum..."
rightsum=`md5sum /home/$USER/backupper/$filename.7z`
rightsum=${rightsum:0:32}

#TRANSFER FILE TO BACKUP LOCATION(S)
   #In a directory?
read -p "Would you like to save your backup somewhere? Specify an existing directory, otherwise just press ENTER. " pathh
if [ "$pathh" != "" ]; then
cp_to_removable
fi

   #On a SMB server?
read -p "Save to SMB server? (y/n) " ans
if [ $ans == "y" ]; then
cp_to_server
fi

read -p "Remove working directory (/home/$USER/backupper) and all of its content? (y/n) " ans
if [ $ans == "y" ]; then
rm -rf /home/$USER/backupper/
fi

echo "DONE"


@-)


Last edited by e633 on Sat Feb 20, 2010 7:08 pm, edited 1 time in total.

Top
 Profile  
 PostPosted: Wed Feb 03, 2010 12:43 pm   
User avatar

Joined: Mon Jan 18, 2010 8:10 pm
Posts: 40
e633 wrote:
- directories to backup are hard-coded cause i couldn't figure out a good way to choose them "at runtime";

Please pardon my newbiness, but have you considered using positional parameters to specify the directories to back-up?
If you only want to back-up one directory, the code would be (something like):
Code:
BACKUP_DIR=$1
BACKUP_DIR=${BACKUP_DIR:?"No Directory Given: Usage: backup [directory1] ([directory2]) ([...])"}
echo "Directory to backup (BACKUP_DIR): $BACKUP_DIR"

If you want to back-up multiple directories, you could get all positional parameters (command line values) with a simple loop and a check for valid directories:
Code:
#backup
echo "backup: $@"
if [ $# = 0 ]; then echo "No Directory Given: Usage: backup [directory1] ([directory2]) ([...])"; exit 0; fi
unset BACK_DIR[*]
let -i count=0
for DIR in $@; do
   let count=count+1
   if [ ! -d $DIR ]; then
      echo "$DIR is not a directory."
      let count=count-1
   else
      BACKUP_DIR[$count]=$DIR
      echo "BACKUP_DIR[$count]: ${BACKUP_DIR[$count]}"
   fi
done
let -i DIRECTORIES=$count
echo "Number of good directories: $DIRECTORIES"
echo "Directories to back-up:"
for (( count = 1; count <= $DIRECTORIES; count++ )); do
   echo ${BACKUP_DIR[$count]}
done

"Positional Parameters", from Learning the bash Shell:
Quote:
The most important special, built-in variables are called positional parameters. These hold the command-line arguments to the scripts when invoked. Positional parameters have the names 1, 2, 3, etc. There is a positional parameter 0, whose value is the name of the script (i.e., the command typed in to invoke it).

Two special variables contain all of the positional parameters (except positional parameter 0): * and @. The difference between them is subtle and important, and it's apparent only when they are within double quotes.

"$*" is a single string that consists of all the positional parameters, separated by the first character in the value of the environment variable IFS (Internal Field Separator), which is a space, TAB, and NEWLINE by default. On the other hand, "$@" is equal to "$1" "$2" "$3"... "$N", where N is the number of positional parameters. That is, it's equal to N separate double-quoted strings, which are separated by spaces. If their are no positional parameters, "$@" expands to nothing. We'll explore this difference in a little while.

The varible # holds the number of positional parameters (as a character string). All of these variables are "read-only," meaning that you can't assign new values to them within scripts.

(Learning the bash Shell [Third Edition], p.86 (Newham and Rosenblatt; O'Reilly; 2005)
http://oreilly.com/catalog/9780596009656/

(Good book!)
C:-)


Top
 Profile  
 PostPosted: Wed Mar 10, 2010 8:18 pm   

Joined: Wed Mar 10, 2010 8:05 pm
Posts: 25
a backup script without rsync? O_o


Top
 Profile  
 PostPosted: Thu Mar 11, 2010 5:28 am   
Moderator
User avatar

Joined: Thu Oct 11, 2007 7:12 am
Posts: 229
Location: London - UK
caibbor wrote:
a backup script without rsync? O_o


when you one day are able to use snapmirror you'll never want to go back to rsync =))


Top
 Profile  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  


BashScripts | Promote Your Page Too
Powered by phpBB © 2011 phpBB Group
© 2003 - 2011 USA LINUX USERS GROUP