0 Replies - 1164 Views - Last Post: 04 January 2008 - 09:11 PM

#1 Tom9729  Icon User is offline

  • Segmentation fault
  • member icon

Reputation: 181
  • View blog
  • Posts: 2,642
  • Joined: 30-December 07

Another Bash backup script

Posted 04 January 2008 - 09:11 PM

Description: See "Installation" section in the script.I wrote this for someone who wanted to learn Bash, so there are more comments than I usually put in my scripts. This script keeps multiple archives of a single directory. Ex. Say you want to backup ~/stuff. ~/stuff changes a lot, and is important, so you want to back it up (and you want to keep revisions of it to prevent a mistake overwriting the good backups. Now unfortunately, you don't have an infinite hard drive, so you're only going to keep 5 revisions of ~/stuff. This script lets you do that. When 5 revisions exist, and you want to make another backup, the oldest revision is deleted to make space.
#!/usr/bin/bash
#
# Description: A simple backup script. Archive a directory, 
#              hang on to a finite number of archives.
#
# Author: Tom Arnold
# 
# License: Do whatever you want. :)
#
# Installation: If you want this to run as a cron job, put
#               it somewhere like '/etc/cron.daily' or
#               '/etc/cron.weekly'. Mileage may vary.
#
#               If you just want to run it manual, execute
#               the script with something like 'sh /path/to/script.sh'.
#
#               Don't forget to customize in the configuration section 
#               below before you run it. :)
##

########################################################
# Configuration                                        #
#                                                      #
# This section consists of variable definitions.       #
# When you define a variable in BASH, you don't use    #
# the '$' sign in front of it. If you reference it     #
# later though, you'll need it (for example, comparing #
# two variables in an if-statement.                    #
########################################################

# The directory in which backups are to be archived.
# Ex. '/home/tom/backups' 
DEST='dest'

# The directory to backup.
# Ex. '/home/tom/important_stuff'
SRC='src'

# Set the archive compression.
# Choices are 'gzip', and 'bzip2'.
#
# 'gzip' is faster, 'bzip2' has better compression.
CMPRS='gzip'

# A prefix to use for the archive files.
NAME='test'

# Number of backups to keep.
NUM='5'

######################################################
# Making the backup.                                 #
#                                                    #
# In this section we will build up a command to run. #
# By the end of this section, the variable $CMD      #
# should be equal to something like                  #
# 'tar cjf test-10-12-07.tar.bz2'.                   #
######################################################

# Run the UNIX date program, and create a new variable
# named 'DATE' with a value equal to whatever UNIX date
# returned (something like '10/12/07').
DATE=$(date +%x)

# Slashes aren't going to look very nice in our filename,
# use a "regular expression" (aka regex) to replace them
# with dashes.
#
# Don't worry about this part too much, regex's are certainly
# useful, but not required for BASH programming.
DATE=${DATE////-}

# Append the date we just got onto the 'NAME' variable.
NAME+=-$DATE

# This variable is where we're going to build our command.
CMD='tar c'

# If compression is set to "gzip", use the 'z' option.
# Otherwise use the 'j' option ("bzip2").
#
# Also, append the rest of the stuff to our command.
if [ $CMPRS == 'gzip' ];
then
    CMD+='zf '"$DEST"/"$NAME"'.tar.gz '"$SRC"
else
    CMD+='jf '"$DEST"/"$NAME"'.tar.bz2 '"$SRC"
fi

# Run the command (make the backup).
$CMD

#####################################################
# Cleanup.                                          #
#                                                   #
# The point of this script is to automate things.   #
# If we keep creating new archives, we're going to  #
# run out of hard disk space eventually. Therefore, #
# we need to do some garbage collection. :)         #
#####################################################

# Iterate through our archive directory.
# Count up how many files we have, and
# collect names and dates.
#
# Note: This part uses arrays. If you have no prior
#       programming experience, these may trip you
#       up. I suggest googling a tutorial on them
#       (C, C++, Java, they're all pretty similar).
N=0

for FILE2 in $DEST/*
do
  FNAMES[$N]=$FILE2
  
  # This uses the UNIX stat program.
  # Again, you don't really need to know about this.
  DATES[$N]=$(stat -c %Y "$FILE2")

  # Increase our file counter by one.
  let N+=1
done

# If we're not over our backup limit, just call it quits.
# Otherwise sort our filenames by date, and delete the oldest
# until we're under our limit again.
K=0
if [ $N -le $NUM ];
then
    #echo "Under the limit, not deleting anything."
    exit
else
    # Sorting time!
    let K=0 # An index variable.

    # While the index ('K') is less than the number of filenames
    # we collected, do this loop.
    while [ $K -lt $N ];
    do
      # Index and value of the maximum.
      let MI=0
      let MAX=0

      # Another index.
      let l=0

      # Iterate through our files and find the oldest.
      while [ $l -lt $N ];
      do
	if [ ${DATES[$l]} -gt $MAX ];
	then
	    let MAX=${DATES[$l]}
	    let MI=$l
	fi

	# Increment 'l'
	let l+=1
      done

      # Add the max from that time arround to a new
      # array. Set the old value to something silly.
      FNAMES2[$K]=${FNAMES[$MI]}
      DATES2[$K]=${DATES[$MI]}
      DATES[$MI]=-10
    
      # Increment 'K'.
      let K+=1
    done
fi

# Count up to the number of backups we want to keep,
# then start deleting.
W=0
while [ $W -lt $N ];
do
    if [ $W -ge $NUM ];
    then
	#echo "Deleting "${FNAMES2[$W]}"
	rm "${FNAMES2[$W]}"
    fi
    
    let W+=1
done


Is This A Good Question/Topic? 0
  • +

Page 1 of 1