V

postpone

A Bash script to postpone some action for a given time

Scope + Example

When a certain job needs to be run often, e.g. some monitoring, but it should do some action only every now and then, postpone can check whether the job was run within some given time by keeping a logfile. In a Bash script, for instance, one could use something along the lines of

if postpone myscriptid "4 hours" ; then
   echo "action postponed"
   # do nothing, have a coffee, chill out ...
else 
   echo "4 hours passed. Let's go"
   # do some more nifty stuff, ...
fi

Let's say we want to know whether some host is on-line. We want to check every 5 minutes but once the host is on-line we want to receive a message only every 4 hours. With postpone we could put the following into a Cron job which runs every 5 minutes:

ping -c1 84.112.111.156 >/dev/null && { postpone ping156 "4 hours" || echo | mail -s "PC 156 is online" $USER ; }

That is, if the ping -c1 returns TRUE – i.e. the host is on-line and responded to the ping, the remaining part after the && will be executed. postpone ping156 "4 hours" will check if it has something logged for "ping156" within the last 4 hours, and it will return TRUE if this is the case, i.e. further action should still be postponed. Hence its name :)

If the postpone returns TRUE execution will stop before the ||. If it returns FALSE mail will send a message.

Of course, one might want do more sophisticated stuff with the above example. Like when you do not want to be notified you might also do not have to check every 5 minutes, i.e. you could also postpone the ping.

Usage

postpone {jobid} "time interval"

The script is fairly simple. jobid should be alpha-numeric, and the "time interval" is handled by date. So everything which is understood by date should be fine. E.g. 1 hour 27 minutes.

Usage disclaimers

My script uses date +%s (a format string for "seconds since 1970-01-01 00:00:00 UTC"). Not all implementations of date support this. Also, no checking on the validity of "time interval" is done. For my personal use this is sufficient (at least until proved otherwise).

The script

Just for reference, here are the core parts. For the full script, please, download it: postpone.sh

# get time of last run (or none if there was none)
LASTRUN=$(grep "^$JOBID [0-9]" $MYLOGFILE | tail -1 | cut -d' ' -f2,3)
 
# there is only 1 case where we return 0 and do nothing else:
# that is when there was a previous run logged and $POSTPONE time is not yet over
if [ "/$LASTRUN/" != '//' ] ; then
   # check time of last run
   # i.e. return 0 if stored date + POSTPONE is in future
   NOWSECONDS=$(date +%s)
   LASTRUNSECONDS=$(date -d "$LASTRUN" +%s)
   POSTPONESECONDS=$(date -d "now + $POSTPONE" +%s)
   POSTPONESECONDS=$((POSTPONESECONDS-NOWSECONDS))
   test $((LASTRUNSECONDS+POSTPONESECONDS)) -gt $NOWSECONDS && exit 0
fi
 
postpone_bashscript.txt · Last modified: 2017-07-30 15:12 by andreas