Ubuntu – How to get an SVN backup cron working

bashcronsvnUbuntu

I'm trying to get the script here working on my Ubuntu Server to backup the SVN repository via a cron.

#!/bin/bash

BACKUP_DIR="/backup/repository"
REPOSITORY_DIR="/home/svn/repository"
#search in repository folder to find all the repository names
ls -Al --time-style=long-iso /home/svn/repository/ | grep '^d' | awk '{print $8}' | while read line
do
    if [ ! -d $BACKUP_DIR"/"$line ]; then
        mkdir $BACKUP_DIR"/"$line
    fi

    #Getting revision number
    REVISION=`cat $REPOSITORY_DIR"/"$line"/db/current" | awk '{print $1}'`

    #Archive last backup
    tar -czf $BACKUP_DIR"/"$line"-last.tar.gz" $BACKUP_DIR"/"$line"/"

    #Dangerous :)
    if [ -n "$BACKUP_DIR" ]; then
    rm -rf $BACKUP_DIR"/"$line"/*"
    fi

    #Check to see if exists a hot backup
    if [ -d $BACKUP_DIR"/"$line"/"$line"-"$REVISION ]; then
        echo "Skipping Backup ! Backup Already Exists"
    else
        echo "Doing backup for "$line
        /usr/bin/svn-hot-backup $REPOSITORY_DIR"/"$line $BACKUP_DIR"/"$line
    fi

done

I've changed the paths to the correct ones, and subversion-tools is installed, however I get the following errors if I try and run sudo bash svnbackup.sh:

: command not foundline 2:
svnfullbackup.sh: line31: syntax error near unexpected token 'done'
svnfullbackup.sh: line31: 'done'

I presume these errors are why the cron didn't work at its alloted time. How can I fix them?

Best Answer

The "command not found" error looks like it was overwritten which is an indication of the wrong type of line endings. Run dos2unix on your script file to fix that. It's possible that it's some other stray character. Display your script using hexdump or cat -v to reveal that. This problem often occurs when you use a Windows editor on a Unix file.

Instead of this line:

ls -Al --time-style=long-iso /home/svn/repository/ | grep '^d' | awk '{print $8}' | while read line

use this:

find "$REPOSITORY_DIR" -maxdepth 1 -type d | while read -r line

which doesn't rely on ls which is not meant for use in scripts/pipes. Doing it this way also is more likely to work in cases where filenames include spaces.

You can do the quoting the way you have it, but this example might be better since it works if there are spaces in filenames:

if [ ! -d "$BACKUP_DIR/$line" ]; then
    mkdir "$BACKUP_DIR/$line"

It's better to use $() instead of backticks and cat is unnecessary (also simplified quoting):

REVISION=$(awk '{print $1}' "$REPOSITORY_DIR/$line/db/current" )

And there are more places where you can simplify quoting.