CSUF LogoCSUF Site Navigation
optics.csufresno.edu

F12 Network/Filesystem Services & Apps  Backups & rsync

Department of Electrical and Computer Engineering
Associate Professor Gregory R. Kriehn
Forums
Wiki
F12 Backups & rsync

Back when I first was learning how to use Linux as a young graduate student, our systems administrator for the research group's network setup remote file distribution and similar such tasks using rdist. Being the naive and enthusiastic learner that I was, I decided to use rdist as well to move files back and forth from my laptop computer to the research group's server. What an absolute pain, especially if my root home-directory structure changed! It was good to learn...once, until I stumbled upon rsync.

rsync is a snap to use. Instead of copying every file from one location to another each time it's run, as is the case with rdist, rsync updates the changes that are made between files, only when necessary. So backups changed from a 10-20 minute job using rdist to a 30 second to 2 minute job (100 Mbits/s helps as well!) using rsync. The process became a whole lot simpler — and safer — in the process.

Backups

There are two locations that I do backups. Every hour I perform a local backup on a separate partition /backup on my server's hard drive; and I also perform hourly, daily, weekly, and monthly backups on a remote RAID 5 server using NFS, which is mounted at /mnt/nfs/backup on my local server. The advantage of this is that at worst, I lose an hour's worth of work. I also have a running history of my filesystem in case I have to access an older changed or deleted file, or if I've done something stupid (which has happened on more than one occasion). If you are planning on doing something similar, see the NFS page for setup instructions.

My backup scripts amount to very simple rsync commands that are placed in an /etc/cron.[] directory.
cron runs jobs through executable files that are placed in these directories at specific times, automating the entire process. I also keep logs of what is occurring, and rotate them on a weekly basis. Let's run through the process:

1.1  Hourly Backups
Hourly backups are performed by creating a file called /etc/cron.hourly/backup-hourly using sudo:
~> sudo nano /etc/cron.hourly/backup-hourly
Add the following information to the file:
#!/bin/sh
# A safe way to do backups...

# Backup contents of /home/[user]/ to /backup/[user]-hourly locally.
rsync -avz --delete /home/[user]/ /backup/[user]-hourly >> /var/log/rsync/backup-hourly-local.log

# Backup contents of /home/[user]/ to /mnt/nfs/backup/[user]-hourly via NFS.
rsync -avz --delete /home/[user]/ /mnt/nfs/backup/[user]-hourly >> /var/log/rsync/backup-hourly.log
The first rsync command "rsync -avz --delete" copies files using archive mode ("-a")to preserve the time stamps, links, to copy recursively, etc., verbosely ("-v"), and using compression for faster data transfers ("-z"). The "--delete" option deletes files that are located in the backup directory that are no longer present in the source directory. Next is the source directory "/home/[user]/". The trailing "/" must be present(!), as it means "copy the contents of this directory", opposed to "copy the directory by name". (See the man page for details.) Then comes the target directory, which in this case is on a local partition "/backup/[user]-hourly". Notice the lack of the trailing "/", which in this case must not be present(!). (Again, see the man page for details.) Finally, since we are using verbose mode, we are going to cat the output of the command and save it to a log file located in /var/log/rsync/backup-hourly-local.log (which we will create).

The second rsync command does something very similar, but in this case copies the files to a mounted NFS directory, which is located on my college's RAID 5 server (it helps to become friends with the IT guys). Save and exit.

Next, we need to make sure that the file is executable so that when cron tries to access it, the script can be executed:
~> sudo chmod ugo+x /etc/cron.hourly/backup-hourly


1.2  Daily backups
Hourly backups are performed by creating a file called /etc/cron.daily/backup-daily using sudo:
~> sudo nano /etc/cron.daily/backup-daily
Add the following information to the file:
#!/bin/sh
# A safe way to do backups...

# Backup contents of /home/[user]/ to /mnt/nfs/backup/[user]-daily via NFS.
rsync -avz --delete /home/[user]/ /mnt/nfs/backup/[user]-daily >> /var/log/rsync/backup-daily.log
Save and exit. Change the permissions:
~> sudo chmod ugo+x /etc/cron.daily/backup-daily


1.3  Weekly backups
Weekly backups are performed by creating a file called /etc/cron.weekly/backup-weekly using sudo:
~> sudo nano /etc/cron.weekly/backup-weekly
Add the following information to the file:
#!/bin/sh
# A safe way to do backups...

# Backup contents of /home/[user]/ to /mnt/nfs/backup/[user]-weekly via NFS.
rsync -avz --delete /home/[user]/ /mnt/nfs/backup/[user]-weekly >> /var/log/rsync/backup-weekly.log
Save and exit. Change the permissions:
~> sudo chmod ugo+x /etc/cron.weekly/backup-weekly


1.4  Monthly backups
Monthly backups are performed by creating a file called /etc/cron.monthly/backup-monthly using sudo:
~> sudo nano /etc/cron.monthly/backup-monthly
Add the following information to the file:
#!/bin/sh
# A safe way to do backups...

# Backup contents of /home/[user]/ to /mnt/nfs/backup/[user]-monthly via NFS.
rsync -avz --delete /home/[user]/ /mnt/nfs/backup/[user]-monthly >> /var/log/rsync/backup-monthly.log
Save and exit. Change the permissions:
~> sudo chmod ugo+x /etc/cron.monthly/backup-monthly


2.  Create a /var/log/rsync directory:
~> sudo mkdir /var/log/rsync
so that when the logs are generated, they will actually be saved where they are supposed to.



3.  Create a /etc/logrotate.d/backups file for log rotation:
~> sudo nano /etc/logrotate.d/backups
Place the following information in the file, which will perform standard weekly log rotation of the logs to keep a running history of what is going on:
/var/log/rsync/backup-hourly-local.log {
        notifempty
        weekly
        missingok
        rotate 4
}

/var/log/rsync/backup-hourly.log {
        notifempty
        weekly
        missingok
        rotate 4
}

/var/log/rsync/backup-daily.log {
        notifempty
        weekly
        missingok
        rotate 4
}

/var/log/rsync/backup-weekly.log {
        notifempty
        weekly
        missingok
        rotate 4
}

/var/log/rsync/backup-monthly.log {
        notifempty
        weekly
        missingok
        rotate 4
}
Save and exit. Backups are complete. See — it's a snap!

rsync Scripts for File Synchronization

Since I do a lot of work on my laptop, and am away from my master file system on this server, I needed to create a simple, but safe and precise way of transferring files back and forth so maintain file synchronization between my server and laptop. As mentioned in the NFS page, my laptop is setup to mount the server's /home and /var/spool/mail directories when an ethernet connection is established at /mnt/nfs/[server]/home and /mnt/nfs/[server]/mail, respectively. When mounted, it is a simple matter to either rsync files from the server to the laptop to keep the laptop /home directory structure current, or to rsync files from the laptop back to the server if I have been doing a lot of remote work to keep the server /home directory structure current. As long as I make sure my laptop is up to date before going on a trip, and rsync it back to the server once I return, my overall file directory structure is always maintained. And because I perform automatic, hourly backups, if I do something really stupid (like transfer files the wrong way), I only — at worst — lose an hour's worth of work. Not bad, not bad at all.

I am by no means a programmer, so this may be kind of cludgy, but it works. First off, I keep the rsync scripts in a ~/linux/rsync directory. Within this directory, there are three additional sub-directories:

~> ls ~/linux/rsync
bin  to_[client]  to_[server]
In the ~/linux/rsync/bin directory, there is a executable single file called "yesno" that I ripped off from IDL that allows a user to be asked a yes/no question when executed. I do this because when I execute my backup scripts, I want to verify that I am actually using the correct one.

The contents of the ~/linux/rsync/bin/yesno file are:

#!/bin/sh
#
#    $Id: yesno,v 1.4 1998/04/02 23:28:57 beth Exp $
#
# This script asks a y/n question of the user:
#
#    $* - The y/n question to ask, without the "(y/n) ?" at the end.
#
# A 0 is echoed for "no", a 1 for "yes".
#

if [ "`echo -n testing123`" = "testing123" ]; then
  ECHO_NONL="echo -n"
  ECHO_NONL_TAIL=
else
  ECHO_NONL=echo
  ECHO_NONL_TAIL=\\c
fi


RESP=""
while [ "$RESP" != y -a "$RESP" != n ]
do
  $ECHO_NONL "$*? (y/n): $ECHO_NONL_TAIL" > /dev/tty
  read RESP
  RESP=`echo $RESP | tr '[A-Z]' '[a-z]'`
  if [ "$RESP" != y -a "$RESP" != n ]; then
    echo "        <Please answer y for yes or n for no>" > /dev/tty
  fi
done
if [ "$RESP" = y ]; then
  echo 1
else
  echo 0
fi

exit 0
Make sure that the file is executable by the local user only (for security reasons):
~> chmod u+x ~/linux/rsync/bin/yesno
Transferring files from the Server to the Client

In the to_[client] directory is an executable script called "backup_[client].sh" (wait!...shouldn't all the executables be in the bin directory? Yeah, yeah, I know — I told you, it's cludgy), and an exclusion file called "exclude_file.txt". When run, the script will verify that the NFS /home directory from the server is mounted on the laptop, and will then proceed to rsync files from the mounted NFS /home directory of the server to the local /home directory on the laptop. So, the purpose of this script is to rsync files from the server to the laptop.

Here are the contents of ~/linux/rsync/to_[client]/backup_client.sh:

#!/bin/sh
# Author: Gregory Kriehn
# Modified From: Brice Burgess - bhb@iceburg.net
# backup.sh -- backup to a local drive using rsync

# Directories to backup. Separate with a space.
SOURCES="/mnt/nfs/[server]/home/[user]/"

# Directory to backup to. This is where your backup(s) will be stored.
# Exclude trailing slash!
TARGET="/home/[user]"

# Your EXCLUDE_FILE tells rsync what NOT to backup. Leave it unchanged
# if you want to backup all files in your SOURCES. If performing a FULL
# SYSTEM BACKUP, ie.  Your SOURCES is set to "/", you will need to
# make use of EXCLUDE_FILE.  The file should contain directories and
# filenames, one per line.
# An example of a EXCLUDE_FILE would be:
# /proc/
# /tmp/
# /mnt/
# *.SOME_KIND_OF_FILE

EXCLUDE_FILE="./exclude_file.txt"

# Comment out the following line to disable verbose output
VERBOSE="-v"
###########################
echo "
       This script will rsync files from the NFS filesystem on
       [server] (the server) to /home/[user] on [client] (the target).

       Make sure that NFS is mounted prior to running the script!
     "

if [ `sh ./../bin/yesno "Execute the rsync command now"` = 1 ]; then
  echo ""
  echo "Updating files on [client]..."
  echo ""

  echo "Verifying sources..."
  for source in $SOURCES; do
    echo "     Checking source $source"
      if [ ! -x $source ]; then
        echo "     Error with $source"
        echo "     Directory either does not exist, or you do not have proper permissions!"
        echo "     Exiting..."
        exit 2
      fi
  done

  echo "     Looking at exclude file..."
  if [ -f $EXCLUDE_FILE ]; then
    EXCLUDE="--exclude-from=$EXCLUDE_FILE"
    echo "       ...Exclude file $EXCLUDE_FILE found!"
  else
    echo "       ...Exclude file not present!"
  fi

  echo "  ...Sources verified."
  echo ""

  echo "Verifying target $TARGET..."
  if [ ! -x $TARGET ]; then
    echo "     Directory either does not exist, or you do not have proper permissions!"
    echo "     Exiting..."
    exit 2
  fi
  echo "  ...Target verified."
  echo ""
  echo "Running rsync..."
  for source in $SOURCES; do

  rsync $VERBOSE --exclude=$TARGET/ $EXCLUDE -a --delete $source $TARGET > rsync.log

  done

fi

exit 0
The script basically asks you to verify that you are going to be copying files from the server to the laptop (hence the use of yesno), and then proceeds to make sure that the source directory is actually mounted. If not, it exits. Next, it looks at exclude_file.txt, which allows you to prevent certain files from being rsync'ed over. This is great, because files and directories like .bash_history, .bash_logout, .e/, .ecore/, .eggcups/, .gconf/, .gconfd/, .gnome/, .gnome2/, .gnome_private/.ICEauthority, .ssh/, .Xauthority, etc. are all specific to the local computer, and should not be subject to rsync (this list is by no means complete). Notice that the script even tells you the form of exclude_file.txt. Use it as a basis to create your own. Finally, the script verifies the presence of the target directory, and then if everything checks out ok, runs rsync to transfer the files and creates a local log called "rsync.log".

Make sure that the file is executable by the local user only (for security reasons):
~> chmod u+x ~/linux/rsync/to_[client]/backup_[client].sh
Transferring files from the Client to the Server

In a similar manner, the to_[server] directory has an executable script called "backup_[server].sh" and its own exclude_file.txt file (which may or may not be the same as your other exclude file, depending upon your needs). When run, the script will verify that the NFS /home directory from the server is mounted on the laptop, and will then proceed to rsync files from the local /home directory on the laptop to the mounted NFS /home directory from the server. So, the purpose of this script is to rsync files from the laptop to the server.

Here are the contents of ~/linux/rsync/to_[server]/backup_server.sh:

#!/bin/sh
# Author: Gregory Kriehn
# Modified From: Brice Burgess - bhb@iceburg.net
# backup.sh -- backup to a local drive using rsync

# Directories to backup. Separate with a space.
SOURCES="/home/[user]/"

# Directory to backup to. This is where your backup(s) will be stored.
# Exclude trailing slash!
TARGET="/mnt/nfs/[server]/home/[user]"

# Your EXCLUDE_FILE tells rsync what NOT to backup. Leave it unchanged
# if you want to backup all files in your SOURCES. If performing a FULL
# SYSTEM BACKUP, ie.  Your SOURCES is set to "/", you will need to
# make use of EXCLUDE_FILE.  The file should contain directories and
# filenames, one per line.
# An example of a EXCLUDE_FILE would be:
# /proc/
# /tmp/
# /mnt/
# *.SOME_KIND_OF_FILE

EXCLUDE_FILE="./exclude_file.txt"

# Comment out the following line to disable verbose output
VERBOSE="-v"
###########################
echo "
      This script will rsync files from the local filesystem on
      [client] (The Source) to /mnt/nfs/[server]/home/[user] on [server]
      (The Target).

      Make sure that NFS is mounted prior to running the script!
     "

if [ `sh ./../bin/yesno "Execute the rsync command now"` = 1 ]; then
  echo ""
  echo "Updating files on [server]..."
  echo ""

  echo "Verifying sources..."
  for source in $SOURCES; do
    echo "     Checking source $source..."
      if [ ! -x $source ]; then
        echo "     Error with $source"
        echo "     Directory either does not exist, or you do not have proper permissions!"
        echo "Exiting..."
        exit 2
      fi
  done

  echo "     Looking at exclude file..."
  if [ -f $EXCLUDE_FILE ]; then
    EXCLUDE="--exclude-from=$EXCLUDE_FILE"
    echo "       ...Exclude file $EXCLUDE_FILE found!"
  else
    echo "       ...Exclude file not present!"
  fi

  echo "  ...Sources verified."
  echo ""

  echo "Verifying target $TARGET..."
  if [ ! -x $TARGET ]; then
    echo "     Directory either does not exist, or you do not have proper permissions!"
    echo "Exiting..."
    exit 2
  fi
  echo "  ...Target verified."
  echo ""
  echo "Running rsync..."
  for source in $SOURCES; do

  rsync $VERBOSE --exclude=$TARGET/ $EXCLUDE -a --delete $source $TARGET > rsync.log

  done

fi

exit 0
Make sure that the file is executable by the local user only (for security reasons):
~> chmod u+x ~/linux/rsync/to_[server]/backup_[server].sh
Conclusion

Is there an even easier, or more elegant way of doing this? Probably. (And if you have a better way, contact me!) But contrary to what these web pages may (or may not) lead you to believe, I am not a "real" Linux systems administrator, or even a real programmer. I am basically a Linux enthusiast and a hacker, in the "let's just hack the code to get it to work" kind of way (not the "I like to crack other people's computer systems" kind of way). Don't get me wrong — I use Linux because of its technical superiority, especially since I am a Professor teaching Electrical and Computer Engineering. But at the same time, there is only so much time in a 24 hour period, and the main goal here is using Linux to increase my productivity.