Special crontab expression - cron

just to verify my understanding of cron-syntax, the following expression will fire on a saturday at 02:42 in the middle of the month, right?
42 02 12-19 * 6 myScript > /dev/null 2>&1
cheers
Nicolaie

The script myScript (not good without a path here!) will be executed at 2:42 indeed, on every day between and including the 12th to the 19th of each month that is a saturday.

Actually
42 02 12-19 * 6 myScript > /dev/null 2>&1
means run on 12 thru 19 and every Saturday.
You need a more complex line to do what you state:
0 4 8-14 * * test $(date +\%u) -eq 6 && echo "2nd Saturday"
is an example from the manfile on my system. It uses a trivial execution after making sure it is Saturday.
See http://www.adminschoice.com/crontab-quick-reference/ as well as > man 5 crontab (at the commandline) for more.

Related

Unix Cron for running job on 1st weekday

Can someone help mw with the cron expression for running job on 1st weekday??
Is it possible in simple unix crontab?
If your week start on Monday and you want to run script every monday you should use something like (suppose you run your script at 22h 00m)
0 22 * * 1 /path/to/script
If you want to run the script first work day of month and your week start on Monday you can try something like:
0 22 1,2,3,4,5,6,7 * * /path/to/script
and add on the begin of the script this:
if [ "$(date +%u) -ne 1 ]
then exit
fi
this will end the script if you run it on day of week which is not Monday

Crontab not running on sunday night

So I made this so it would send a command at Sunday night at 11:59pm, 1 minute before Monday, but for some reason it doesn't work. I even changed the * * 7 to 0.
59 23 * * 7 screen -S skyblock -p 0 -X stuff "mangdelp default essentials.fly ${printf \\r)"
Your syntax is incorrect.
It should be like this:
59 23 * * 0 screen -S skyblock -p 0 -X stuff \"mangdelp default essentials.fly ${printf \\r)\" >/dev/null 2>&1
minute(s) hour(s) day(s) month(s) weekday(s) command(s)
The fields are
separated by spaces or tabs. The first five are integer patterns and
the sixth is the command to be executed. The following table briefly
describes each of the fields.
Field Value Description
minute 0-59 The exact minute that the command sequence executes
hour 0-23 The hour of the day that the command
sequence executes
day 1-31 The day of the month that the command
sequence executes
month 1-12 The month of the year that the command
sequence executes
weekday 0-6 The day of the week that the command
sequence executes. Sunday=0, Monday = 1, Tuesday = 2, and so forth.
command Special The complete sequence of commands to be executed. The
command string must conform to Bourne shell syntax. Commands,
executables (such as scripts), or combinations are acceptable.

Are there cron-expressions to run a script every ninth minute?

I'd like to run a bash command every 9th minute and every 70th minute.
man -S 5 crontab says:
Steps are also permitted after an asterisk, so if you want to say "every two hours", just use "*/2".
I ran the command
echo "Cron-job runs. ($(date))" >> crontest.log
with the cron expression
*/9 * * * *
which gave me
Cron-job runs. (We 25. Mar 13:27:01 CET 2015)
Cron-job runs. (We 25. Mar 13:36:01 CET 2015)
Cron-job runs. (We 25. Mar 13:45:01 CET 2015)
Cron-job runs. (We 25. Mar 13:54:01 CET 2015)
Cron-job runs. (We 25. Mar 14:00:01 CET 2015)
Cron-job runs. (We 25. Mar 14:09:01 CET 2015)
Cron-job runs. (We 25. Mar 14:18:01 CET 2015)
It seems, that */9 means "every minute that can be divided by nine without remainder" (this includes zero!) instead of "every ninth minute".
Are there cron-expressions to define intervals?
No, there is no facility for this specific use case. You could create a complex crontab which lists all the combinations;
0-54/9 0-21/3 * * * crontest
3-57/9 1-22/3 * * * crontest
6-51/9 2-23/3 * * * crontest
(This complex syntax is an extension, but since you were asking about */9 which is a similar extension, you should be able to use the above as well. See an earlier version of this answer for the full-hand syntax, which however I incorrectly identified as extended in my original answer.)
For execution every 70 minutes, a similar table would be a lot more complex, because 70 is not evenly divisible by 1440 (24*60). You end up with a periodicity over multiple days, so the table gets so complex as to beg for alternative solutions.
... One of which would be to use a self-scheduling at job:
#!/bin/sh
echo "$0" "$#" | at now + 70 minutes
:
# the rest of your crontest script here
You need to start this one manually the first time, but it will keep scheduling new jobs after that. (If your server is down for an extended period of time, you may need to restart it; but the job should survive the occasional quick reboot just fine.)
Or you could run your script every minute, and the script can check if it's the right time to run.
untested
#!/bin/bash
minute_of_the_epoch=$(( $(date +%s) / 60 ))
(( minute_of_the_epoch % 9 != 0 )) && exit
# rest of script ...

Setting cron job end time

I want to set up a cron job which will execute a command every hour. However, I want that this command should be started at 10 A.M and should run every hour till 4 P.M. This job is to run daily between these times. The command is nothing but a call to a Perl script. Following crontab entry runs fine and invokes the script every hour
* */1 * * * cd path_to_file; perl file.pl > path_to_logs/log.txt
Is there a way to limit the timings of this cron job so that it runs only between 10 A.M and 4 P.M ?
man 5 crontab is your friend. (Your example does not do what you claim it does; /1 is the default skip and therefore redundant, and that spec therefore runs once per minute due to the leading * instead of 0.)
0 10-15 * * * your command here
(I used 15, because it occurs to me that "between 10 and 4" is an exclusive range so you don't want to run at 16:00.)
If you want the script to be run every hour you can do something like this:
[code]
00 10,11,12,13,14,15,16 * * * cd path_to_file; perl file.pl > path_to_logs/log.txt
[/code]
This means when the minutes hit 00 and the hour hits any of 10 11 12 13 14 15 16 the script will be run
In your Perl script (or in a wrapper for the Perl script), you can use localtime to check the hour and exit if it isn't between 10am and 4pm:
use strict;
use warnings;
my #lt=localtime;
my $hour=$lt[2];
unless($hour>=10 and $hour<=16)
{
print "Not between 10am and 4pm. Exiting.\n";
exit;
}
#put the rest of your code here.

How do I make cron run something every "N"th minute, where n % 5 == 1?

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?
1-56/5 * * * * /my/script
This should work on vixiecron, I'm not sure about other implementations.
Use your first schedule:
*/5 * * * * /my/script
And add this to the start of your script:
sleep 60
(Yes, this is a joke)
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
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
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.

Resources