In bash/ash how to construct logic for checking cron?

196 views Asked by At

I'm trying to create a script that will compare cron and if current day/time is within cron start/stop time then perform a function. If there were only one cron entry for start/stop this would be simple but I can't figure out how to allow for multiple crons. I'm using posix/ash but if anyone could offer a bash example hopefully I can adapt it. I'm just stuck understanding how to construct the logic?

Eg: If cron was this, it would be a simple if statement:

00 09 * * Mon,Tue,Wed,Thu,Fri,Sat,Sun /usr/bin/wifi_schedule.sh start
00 11 * * Mon,Tue,Wed,Thu,Fri,Sat,Sun /usr/bin/wifi_schedule.sh stop

But if there are multiple crons, I'm not sure how to approach this:

00 09 * * Mon,Tue,Wed,Thu,Fri,Sat,Sun /usr/bin/wifi_schedule.sh start
00 11 * * Mon,Tue,Wed,Thu,Fri,Sat,Sun /usr/bin/wifi_schedule.sh stop
00 15 * * Mon,Tue,Wed,Thu,Fri,Sat,Sun /usr/bin/wifi_schedule.sh start
00 17 * * Mon,Tue,Wed,Thu,Fri,Sat,Sun /usr/bin/wifi_schedule.sh stop
00 19 * * Mon,Tue,Wed,Thu,Fri,Sat,Sun /usr/bin/wifi_schedule.sh start
00 21 * * Mon,Tue,Wed,Thu,Fri,Sat,Sun /usr/bin/wifi_schedule.sh stop

I've tried using while but that only seems to action the first match or goes into loop.

What I'm trying to do is call the start wireless function if it matches cron. Eg if the device boots after cron start time and before cron stop time then start wireless, or stop wireless if it boots after cron stop. Some things I've tried so far are:

Get current $day and $hour

day=$(date +%a) & hour=$(date +%H)

Get cron $start and $stop times for $day

start=$(grep $day /etc/crontabs/root | awk '/start/ {print $2}')
stop=$(grep $day /etc/crontabs/root | awk '/stop/ {print $2}')

Count how many start/stop times occur (eg $count=3)

count=$(echo "$start" | wc -l)

Create variables for start/stop

set -- $start
set -- $stop

Determine variables from $count=3 (eg -- $3, $2, $1)

var=$(eval echo \$$count)

My failed example of using while:

while [ $var -le $hour ];
  do
    if [ $hour -ge $var ]; then
      echo "do something"
    else
      var=$(eval echo \$$count)
      count=$(( $count - 1 ))
      echo "do something else"
    fi
  done
exit

Any guidance with this would be greatly appreciated, thank you.

1

There are 1 answers

3
umläute On BEST ANSWER

parsing crontabs to find out if a job is supposed to be run looks fundamentally wrong to me. what if there's another crontab running the same set of scripts? what if the scripts have been run manually? what if you switch the cron-logic to systemd.timers?

it seems that what you really want to do is check whether the system is in a given state (e.g. "WiFi is turned on" or even "WiFi should be turned on").

so what you really should do is try to find out whether the system is in the requested state or not.

it could be as simple as setting a flag in the scripts that are executed by cron.

e.g. your wifi_schedule.sh script (which you really should put into /usr/local/bin/ , as /usr/bin is reserved for the system):

#!/bin/sh
case "$1" in
  start)
     echo 1 > /var/run/wifi_schedule
     ;;
  stop)
     echo 0 > /var/run/wifi_schedule
     ;;
esac

# here comes the actual script:
# ...

if the actual task at hand is more complex, you could consider switching from cron to systemd.unit (obviously only if systemd is acceptable to you), which allows you to express timing, execution order and dependencies between its parts.