0

I'm trying to write a small backupscript which should get executed every hour via cronjob.

While the script does monthly/weekly/daily backups and these work, i also would like to perform hourly backups - but only on specific hours. (Like i have a cluster of 3 nodes and want to perform the backup every hour on a different node).

Right now, i want to perform the hourly backups on the following hours

BACKUP_HOURLY=true
BACKUP_RETENTION_HOURS=2,5,8,11,14,17,20,23

And I'm checking for current hour via

HOUR=`date +%H`

I tried something like

if [[ ( $BACKUP_HOURLY == true ) && ( $HOUR -eq $BACKUP_RETENTION_HOURS ) ]]; then
 /usr/local/bin/backup
fi

But this doesn't seem to work. While I also tried googling for a solution I'm probably unable to match the correct search terms to find an easy solution to this problem. Hope anyone can help :-)

quarkz
  • 3
  • 1
  • 2
    Why not use `cron`? or systemd timer? Just type those hours into cron and you're ready to go... – KamilCuk Dec 01 '20 at 16:54
  • The script is being used to perform backups hourly/daily/weekly/monthly and also rotate backups/delete old ones. If there is any "easy" solution to have this logic directly inside the script i would prefer that and just run the script every hour. – quarkz Dec 01 '20 at 16:57
  • 1
    There is a tool, specifically created for one purpouse, to do some action hourly/daily/weekly/monthly. It's `cron`. Nowadays superseded (mostly, but not fully) by systemd-timer. You are reinventing the wheel - the wheel has been invented a long time ago and it's a really really good wheel. – KamilCuk Dec 01 '20 at 17:41
  • `bash`, or `sh`? `[[` doesn't exist in a feature in `sh` at all; they're different languages; don't tag for both. – Charles Duffy Dec 01 '20 at 20:26
  • @tripleee string_contains will find single digit `3` into `BACKUP_RETENTION_HOURS=2,5,8,11,14,17,20,23`, wrongly validating 3 hour. – Léa Gris Dec 02 '20 at 13:53
  • 1
    The trick is to look for `,3,` in `,$BACKUP_RETENTION_HOURS,` – tripleee Dec 02 '20 at 14:00

3 Answers3

0

As some of the others have said, I think there are better ways of running things on timers, such as cron. However, something like this should work for your specific case:

BACKUP_HOURLY=true
BACKUP_RETENTION_HOURS=2,5,8,11,14,17,20,23
HOUR=`date +%H`

if [[ ( $BACKUP_HOURLY == true ) && ( ",$BACKUP_RETENTION_HOURS," =~ .*,$HOUR,.* ) ]]; then
  /usr/local/bin/backup
fi
0

Backup retention hours can be turned into a bit-mask for instant comparison

#!/usr/bin/env sh

BACKUP_RETENTION_HOURS=2,5,8,11,14,17,20,23

retention_mask=0

# Transform retention hours into a bit-mask
IFS=,
for i in $BACKUP_RETENTION_HOURS; do
  retention_mask=$((retention_mask | (1<<i) ))
done

hour=$(date +%H)
if [ $(( (1<<hour) & retention_mask )) -gt 0 ]; then
  echo 'doing backup'
fi
Léa Gris
  • 17,497
  • 4
  • 32
  • 41
0

Awk alterative passing variables into awk using -v:

awk -v rethrs=$BACKUP_RETENTION_HOURS -v hrly=$BACKUP_HOURLY 
     '{
        split(rethrs,map,","); # Split the rethrs variable in an array map using , as the delimiter
        for (i in map) 
                     { 
                       if ( map[i]== strftime("%H") && hrly=="true" ) # Loop through each entry in the map array comparing the entry to the current time (strftime("%H"))
                                                                     { 
                                                                       system( "/usr/local/bin/backup"); # Run the backup using awk's system function
                                                                       break 
                                                                      } 
                      } 
         }' <<< /dev/null

On liner

awk -v rethrs=$BACKUP_RETENTION_HOURS -v hrly=$BACKUP_HOURLY '{split(rethrs,map,",");for (i in map) { if ( map[i]== strftime("%H") && hrly=="true" ) { system("/usr/local/bin/backup");break } } }' <<< /dev/null
Raman Sailopal
  • 12,320
  • 2
  • 11
  • 18