Samstag, 3. November 2012

anacron simulation on a Synology NAS

This is a post not directly related to Android, but to my NAS where I am storing all my personal files. I bought the Synology DS212+ some month ago and I am very happy with it. Having two 2TB hard disks build in, another external harddisk is connected via USB 3.0 for backup resons. This Harddisk I am switching on and off manually from time to time and when it is switched on, a cron job should back up all the files of the DS using rsnapshot to my backup disk.

On a first glance this should not be such a big problem, but digging into it there are some problems to be solved:

  1. starting the backup once via cron, the external harddisk might be switched off and no backup will be done :(
  2. starting the backup regularly via cron might lead to multiple backups for a single day :(

Unfortunately Synology is not providing anacron which provides the possibility to specify such "run once a period" tasks. I digged a bit around, but I couldn't find a simple suitable solution for my needs, so I wrote a small shell script which does the trick:

#!/bin/ash
#
# shell script to run a job once a period
# it takes three parameters:
# - name of the runfile
# - period definition ("1 day", "2 days", ..., "1 week", "2 weeks", ... "1 month", etc.)
# - program to be executed (i.e. backup-program / script)
#
#
# some helper functions
#

date2stamp () {
    date --utc --date "$1" +%s
}

stamp2date (){
    date --utc --date "1970-01-01 $1 sec" "+%Y-%m-%d %T"
}

dateDiff (){
    case $1 in
        -s)   sec=1;      shift;;
        -m)   sec=60;     shift;;
        -h)   sec=3600;   shift;;
        -d)   sec=86400;  shift;;
        *)    sec=86400;;
    esac
    dte1=$(date2stamp $1)
    dte2=$(date2stamp $2)
    diffSec=$((dte2-dte1))
    echo $((diffSec/sec))
}
###########################################################
#
#main program
###########################################################
EXECUTE="0"
RUNFILE=/var/run/$1
LOCKFILE=/var/run/"$1".lock
if [ -f $LOCKFILE ]
then
        echo "other process running -> exiting" >> /var/log/runOnce.log
        exit 2
fi  
touch $LOCKFILE
#      
# check whether runfile exists
#      
NOW=`date -d 'now' --iso-8601`
if [ -f $RUNFILE ]
then
        NEXTRUN=`cat $RUNFILE`
        # check wether next run date is in the past
        if [ `dateDiff -d "$NEXTRUN" "$NOW"` -ge 0 ]
        then
                EXECUTE="1"
        fi
else
        # did not run yet -> run forced
        EXECUTE="1"
        NEXTRUN=`date -d 'now' --iso-8601`
fi

if [ "$EXECUTE" == "1" ]
then    
        # execute (i.e. backup)
        $3
        STATUS_CODE=$?
        if [ $STATUS_CODE -eq 0 ]
        then
                # set next execution date
                while [ `dateDiff -d "$NEXTRUN" "$NOW"` -ge 0 ]
                do
                        # add period
                        NEXTRUN=`date -d "$NEXTRUN + $2" --iso-8601`
                done
                # set next execution date
                echo $NEXTRUN > $RUNFILE
        fi      
fi      
rm $LOCKFILE
exit 0

This script in combination with some entries in my crontab did the trick. ;)

0 18-23 * * * root /root/runOnce.sh backupDaily "1 day" /root/runDailyBackup.sh
20 18-23 * * * root /root/runOnce.sh backupWeekly "1 week" /root/runWeeklyBackup.sh
40 18-23 * * * root /root/runOnce.sh backupMonthly "1 month" /root/runMonthlyBackup.sh

3 Kommentare:

  1. I had to correct the script, because there was an error in calculation for the next run when using a daily difference.

    AntwortenLöschen
  2. Another minor correction: I had to remove the "sh" within the crontab configuration, otherwise it run into an endless loop.

    AntwortenLöschen
  3. New version: some minor improvemts and bugifxes

    AntwortenLöschen