Backup each Samba share to a separate archive

Posted: July 16th, 2009 | Author: | Filed under: Backup | No Comments »

The backup script that I use on my Samba file servers, stores each Samba share in a separate cpio archive (i.e. in a separate backup file). I find such share-based backup arrangements very convenient.

My script – see below – extracts share names and paths from Samba configuration file. When a new share is configured in Samba, it is automatically added to backups.

The script runs full backup followed by 30 incremental backups. After 30 incrementals, the cycle repeats itself – full + 30 incrementals. The script keeps track of the count for each share (their counts do not have to be in sync).

I have used it under Linux and Open Solaris operating systems. It should work without modifications or with minimal modifications under most Unices.

I run the script daily via cron with the following entry:

10 21 * * * /etc/backup/backup_samba_shares.csh > /var/log/Samba_backups/`date +\%Y\%m\%d`.log 2>&1

Note that it is a C-shell script. Many Linux distributions do not install csh/tcsh in default installation. You may need to install it before using the script. (Why C-shell?  Because I am most comfortable with C-shell – this was default shell on IRIX Unix, and this was my first Unix system – this was obviously very many years ago).

If you are interested in using my script, it is listed below. You can directly download it from here

#!/bin/csh

## This script backs up directories that are served by a local Samba server.
## It uses cpio to back up to a file (i.e. to a disk). Separate cpio archive
## is created for each Samba share.
##
##   Karol M. - July 2007

## These are the only variables that you should need to adjust.
## You must create $backupconfig and $destination before running the script.
##
set backupconfig = /etc/backup
set backupvolume = /disk750
set destination = $backupvolume/Samba_backups
set sambaconfig = /etc/samba/smb.conf

## check whether backup volume is mounted
##
/bin/mount -v | grep $backupvolume > /dev/null
if ($status) then
  echo "$backupvolume is not mounted, exiting"
  exit 1
endif

## create backup destination folder (variable $backup)
##
set backup = ${destination}/`/bin/date "+%Y%m%d"`
if (! -e $backup) then
  mkdir -p $backup
endif
if (! -e $backup) then
  echo "$backup has not been created, exiting"
  exit 3
endif

## can we read Samba configuration file?
##
if (! -r $sambaconfig) then
  echo "Cannot read samba configuration file, exiting"
  exit 4
endif

## get a list directories to back up from Samba configuration file
##
cat <<'eoof' > awkin$$
/^\[.*\]/ && !/\[global\]/  { getline; print $3 }
'eoof'
set sambalist = `awk -f awkin$$ $sambaconfig`
rm -f awkin$$
echo "$sambalist"

## Check whether directories are not empty using du.
## $backupdirs holds the list of non-empty Samba dirs - these are
## directories that we are going to back up.
## Note that 'du -ks' is used to check the size of directories, and
## thus returned value depends on the filesystem blocksize. In my
## case, the blocksize is 4096 and thus directory of 4kB is empty.
##
set backupdirs = ""
foreach dir ($sambalist)
  set aa = `du -ks $dir | awk '{print $1}'`
  if ($aa > 4) then
    set backupdirs = "$backupdirs $dir"
  endif
end

## If you do not care whether directories are empty or not,
## comment out the whole section above, and uncomment the lines below
##
# set backupdirs = ""
# foreach dir ($sambalist)
#   set backupdirs = "$backupdirs $dir"
# end

## Check if necessary control files exist, if not, create them.
##
cd $backupconfig
foreach dir ($backupdirs)
  set aa = `echo $dir | sed 's|.*/||g'`
  if (! -e .last---$aa) then
    touch .last---$aa
  endif
  if (! -e .count---$aa) then
    echo "0" > .count---$aa
  endif
end

## read the backup count and perform the backup
## if backup count =0 or >30 - full backup
## if backup count is between 1 and 30 - incremental backup
## other values (such as negative) - no backup
##
foreach dir ($backupdirs)
  set date = `/bin/date '+%Y%m%d-%H%M'`
  set aa = `echo $dir | sed 's|.*/||g'`
  set count = `/bin/cat .count---$aa`
  if ( ( $count == 0 ) || ( $count > 30 ) ) then
## performing full backup
    set backupfile = ${aa}_${date}_full.cpio.bz2
    echo $date > .tmp-${aa}-$$
    echo "=================================================="
    echo "Full backup for $dir on $date"
    echo "Using command: find $dir -depth -print | cpio -ov | bzip2 > $backup/$backupfile"
    echo ""
    find $dir -depth -print | cpio -ov | bzip2 > $backup/$backupfile
    echo ""
    echo -n "Backup command terminated with status $status on "
    set dd = `/bin/date '+%Y%m%d-%H%M'`
    echo "$dd"
    echo ""
    echo ""
    mv -f .tmp-${aa}-$$ .last---$aa
    set count = 1
    echo $count > .count---$aa
  else if ( ( $count < 31 ) && ( $count > 0 ) ) then
## performing incremental backup
    set backupfile = ${aa}_${date}.cpio.bz2
    echo $date > .tmp-${aa}-$$
    echo "=================================================="
    echo "Incremental backup # $count for $dir on $date"
    echo "Using command: find $dir -depth -newer .last---$aa -print | cpio -ov | bzip2 > $backup/$backupfile"
    echo ""
    find $dir -depth -newer .last---$aa | cpio -ov | bzip2 > $backup/$backupfile
    echo ""
    echo -n "Backup command terminated with status $status on "
    set dd = `/bin/date '+%Y%m%d-%H%M'`
    echo "$dd"
    echo ""
    echo ""
    mv -f .tmp-${aa}-$$ .last---$aa
    @ count++
    echo $count > .count---$aa
  else
  ## no backup
    echo "=================================================="
    echo "No backup for $aa - the count is $count"
    set dd = `/bin/date '+%Y%m%d-%H%M'`
    echo "$dd"
    echo ""
    echo ""
  endif
end


Leave a Reply