1

I need a cron to run my task every 50 minutes, starting from now exactly.

Suppose it is now 12:10.

So my task must be run at 13:00, 13:50, 14:40, 15:30, 16:20, 17:10, 18:00, ...

I tried various crontab expressions but none of them work;

  • */50 * * * * runs at 12:50, 13:40, ....
  • */50 13/1 * * * runs at 13:00, 13:50, 14:00, ....
  • 0,50,40,30,20,10/50 * * * * runs at 12:20, 12:30, 12:40, ....

Any idea how I could express this?

tripleee
  • 175,061
  • 34
  • 275
  • 318
Sadegh
  • 639
  • 1
  • 5
  • 14

1 Answers1

3

No, there is no notation in Vixie cron to schedule something at intervals which are not an even multiple of something. You have to resort to the standard practice from before Vixie cron (which is only standard on Linux anyway), which is simply to enumerate the times.

 0  0,5,10,15,20 * * * yourjob
50  0,5,10,15,20 * * * yourjob
40  1,6,11,16,21 * * * yourjob
30  2,7,12,17,22 * * * yourjob
20  3,8,13,18,23 * * * yourjob
10  4,9,14,19    * * * yourjob

For simplicity, this makes the last interval before midnight shorter - only 40 minutes instead of 50 - to avoid having to spell out an even more monstrously complex schedule.

Alternatively, you could run a single cron job just before midnight which schedules at jobs for the next 24 hours.

59 23 * * *    yourschedule

where yourschedule might be something like

#!/bin/bash
for ((i=0; i<60*24; i+=50)); do
    echo yourjob | at $((i/60)):$((i%60))
done

Or use a self-scheduling at job, which "plants" the next run 50 minutes from now, forever:

#!/bin/bash
echo "$0" | at "+50 minutes"
# ... your original yourjob script here ...

(Not sure your at will support that time indicator; consult its man page and/or experiment. atq shows what jobs you have queued, and atrm lets you remove a job.)

In some scenarios, perhaps it's easier to just run yourjob every 10 minutes, and have it abort immediately if it's less than 45 minutes since it last ran. (Then you have to make it keep track of when it ran, but it doesn't have to be very involved - probably touch a flag file so its change date indicates the last run.

#!/bin/bash
if (($(date +%s) - $(stat -c '%Y' .lastrun.50min) < 45*60)); then
    exit 0
fi
touch .lastrun.50min
# ... Your original yourjob script here

stat -c '%Y' is GNU/Linux; for other platforms, the syntax will be slightly different.)

Before Paul Vixie's cron implementation was picked up by Linux and became popular, crontab generally didn't permit periodic notations like */5. Back then, you always had to spell out times, like 5,10,15,20,...

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • thanks for your answer. in both your solution, you need to keep track and I can't. (in first solution you need to keep track to get first run time in next 24 hours) – Sadegh Nov 28 '20 at 05:18
  • I don't understand your comment. Keep track of what? The first schedule will start operating immediately; the next run will happen within 50 minutes. If you want it on the next even minute, obviously recalculate the minutes to accommodate that. Then you also risk missing the "now" run if, for example, you run `crontab` on 01:23:59 and the clock rolls past 01:24:00 before `crontab` finishes installing the schedule. – tripleee Nov 28 '20 at 08:39
  • Suppose you schedule task for 24 hours, and last run time is 23:20, then at 23:59 you want to schedule for next 24 hourse, so your schedule must be start from 00:10:00 , and at next day your schedule must be start from 00:20:00. so you need store last run time of day, to decide about "what is first run time at next day?" – Sadegh Nov 29 '20 at 12:52
  • Then go with the self-scheduling `at` job (third example). – tripleee Nov 29 '20 at 12:54