48

I know that I can have something run every five minutes in cron with a line like:

 */5 * * * * /my/script

What if I don't want it running at 12:00, 12:05, 12:10, but rather at 12:01, 12:06, 12:11, etc? I guess I can do this:

 1,6,11,16,21,26,31,36,41,46,51,56 * * * * /my/script

...but that's ugly. Is there a more elegant way to do it?

Jon 'links in bio' Ericson
  • 20,880
  • 12
  • 98
  • 148
mike
  • 46,876
  • 44
  • 102
  • 112

5 Answers5

81
1-56/5 * * * * /my/script

This should work on vixiecron, I'm not sure about other implementations.

David Z
  • 128,184
  • 27
  • 255
  • 279
  • Same syntax is also accepted by fcron, which covers the two most prevalent crons. I do not believe that dcron supports this, but that's rarer. – ephemient Jan 25 '09 at 04:10
  • How do I tell which version of cron is being used? – Aaron J Lang Jan 10 '14 at 17:15
  • @AaronJLang Check your distribution's package manager to see which packages with cron in the name are installed (and in particular, which package has installed the file `/usr/sbin/cron`). Other than that, I'm not sure if there's an easy way to check that works on all distributions. If it's vixiecron, there will probably be some filenames matching `*vixie-cron*` on your system, and you can try the analogous method for other cron implementations. However if you want a "clean" cross-distribution method, perhaps ask on [unix.SE]. – David Z Jan 10 '14 at 17:25
  • 1
    Hey, it works for me, but I dont understand this expression. Can anyone explain how it works? I would also like to make schedule every 7, 12, 22 and 8, 13, 23 etc.. and I'm not sure how to poroceed – Mat Feb 01 '17 at 14:24
  • @Mat let me edit the post with an explanation shortly – David Z Feb 01 '17 at 16:56
  • @Mat see [here] (https://unix.stackexchange.com/a/141177/29426) for explanation of the slash. – akhan Jul 17 '19 at 22:50
18

Use your first schedule:

*/5 * * * * /my/script

And add this to the start of your script:

sleep 60

(Yes, this is a joke)

Sean Bright
  • 118,630
  • 17
  • 138
  • 146
0

This is quite an old topic, however as so much time has passed there are a few other options now. One of which is not to use cron at all, and use systemd timers. Using these gives you a higher granularity than seconds along with lots of other options

More information is available here https://wiki.archlinux.org/index.php/Systemd/Timers

eg to run a adhoc command

# systemd-run --on-calendar="*:1/5" /bin/touch /tmp/foo2
Running timer as unit run-r31335c4878f24f90b02c8ebed319ca60.timer.
Will run service as unit run-r31335c4878f24f90b02c8ebed319ca60.service.

# systemctl status run-r31335c4878f24f90b02c8ebed319ca60.timer
● run-r31335c4878f24f90b02c8ebed319ca60.timer - /bin/touch /tmp/foo2
   Loaded: loaded
Transient: yes
  Drop-In: /run/systemd/system/run-r31335c4878f24f90b02c8ebed319ca60.timer.d
           └─50-Description.conf, 50-OnCalendar.conf, 50-RemainAfterElapse.conf
   Active: active (waiting) since Wed 2017-10-25 09:05:13 UTC; 40s ago

# ls -l  /tmp/foo*
-rw-r--r-- 1 root root 0 Oct 25 09:06 /tmp/foo2

# sleep 300; ls -l  /tmp/foo*
-rw-r--r-- 1 root root 0 Oct 25 09:11 /tmp/foo2

# date; ls -l /tmp/foo2
Wed Oct 25 09:21:42 UTC 2017
-rw-r--r-- 1 root root 0 Oct 25 09:21 /tmp/foo2

edit: these type of timers wont persist over reboot, if you want them to make sure you generate a proper service file, with the relevant oncalendar line

krad
  • 1,321
  • 1
  • 15
  • 12
-1

I'd create a new script "delaystart" that takes a sleeping period as first parameter and the script to run as the rest. I'd make the script check the crontab line for the line with the script and only start the script if the line is not commented out. That makes it reusable, and ps won't report the script as running when it really isn't.

#!/bin/bash
sleeptime=$1
sleep ${sleeptime}
shift
if ( ! crontab -l | grep -e '#.+delaystart '${sleeptime} $* ) then
  $*
fi
Ludvig A. Norin
  • 5,115
  • 7
  • 30
  • 34
-5

sean.bright's joke got me thinking... why not use...

* * * * * /my/script

...and within the script do this...

#!/bin/bash
export WHEN=`date '+%M'`
echo $WHEN
export DOIT=`echo "$WHEN % 5" | bc` 
echo $DOIT
if [ $DOIT != 0 ] ; then
    echo "ha ha ha"
fi
echo "done"

...a kludge... maybe, but as ugly as the crontab... I don't know.

dacracot
  • 22,002
  • 26
  • 104
  • 152