Crontab days exceptions Linux - linux

I have a crontab job that works from monday to friday, but i need it to make exceptions of an specific day, for example the January 1st, the April 11th, etc.
How can i make that exception on my crontab job?
* * * * 1-5 ./full-backup

The easiest way is to use an and or or list sequence.
man sh: AND and OR lists are sequences of one of more pipelines separated by the && and || control operators, respectively. AND and OR lists are executed with left associativity.
An AND list has the form command1 && command2.
command2 is executed if, and only if, command1 returns an exit status of zero.
An OR list has the form command1 || command2. command2 is executed if and only if command1 returns a non-zero exit status.
If you want to exclude 2 days from your cron, lets say the first of January and April 11th, then you can do the following:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
* * * * 1-5 [ `date '+\%m\%d'` == "0101" ] || [ `date '+\%m\%d'` == "0411" ] || ./full_backup.sh
From the moment you have more days to exclude it becomes a bit more tricky. You could use a smaller script like excludedaycmd
#!/usr/bin/env bash
while [[ $1 != "" ]]; do
[[ $(date "+%m%d" )) == $1 ]] && exit 1
shift
done
exit 0
This script will exit with 1 if any of its arguments fit a day. Your cron would look then like.
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
* * * * 1-5 excludedaycmd 0101 0411 && ./full_backup.sh
Any other script can also be used in any other form.

Related

Crontab to run at two hours out of the day, but for one of those hours exclude certain days of the week

I need to change the below schedule to exclude Tuesday and Thursday for only the 2nd hour.
0 2,20 * * *
I want to run a job everyday at 2 am and 8pm, but on Tuesdays and Thursdays exclude the 2 am job.
The easiest answer is going to be two separate entries in your crontab:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
* 2,20 * * 0,1,3,5,6 root /path/to/command.sh
* 20 * * 2,4 root /path/to/command.sh
Make sure that command.sh isn't in an /etc/cron.* folder.
I think all you need is
0 2,20 * * 1,3,4,6,7
the numbers at the end are the days of the week. O being Sunday.

CRON with AND relationship between mday and wday

I have seen this question which indicates that the relationship between the wday and mday fields of a CRON schedule is an OR relationship. Say for example I want to schedule something for every Friday the 13th.
Rather than the expected result, the CRON
0 0 13 * 5
will give me all Fridays of every month, as well as every 13th of every month.
Is there any way to avoid this behavior and specify an AND relationship? (There seems to be mention of older versions using an AND relationship, however I would prefer to use a single tool with the ability to do both)
I guess, instead of specifying the wday (Friday=5), you'll just have to specify the months where the 13th is a Friday; so, for 2019:
0 0 13 9,12 * : do stuff, but avoid black cats
Or, eternally more elegant, create a small script:
$> cat /home/me/bin/test_friday_13
#!/bin/bash
if [ "$(date +'%A %d')" != "Friday 13" ]
then
exit 1
else
: do stuff, but avoid black cats
exit 0
fi
and make the crontab entry:
0 0 13 * * /home/me/bin/test_friday_13
The script approach has the added benefit that you can run it from the command line. (Note: do not forget to alter the weekday name in the script to reflect your environment.)
The cron-entry you are interested in is:
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
0 0 13 * * [ $(date "+\%u") = "5" ] && command
This will execute the cronjob every 13th of the month. It will compute the day of the week, and test it if it is a Friday (5). If so, it will execute command.
Extended explanation:
If you want to have special conditions, you generally need to implement the conditions yourself with a test. Below you see the general structure:
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
0 0 13 * * /path/to/testcmd && command
The command testcmd generally returns exit code 0 if the test is successful or 1 if it fails. If testcmd is successful, it executes command. A few examples that use similar tricks are in the following posts:
Linux crontab for nth Satuday of the month
Is it possible to execute cronjob in every 50 hours?
Cron expression to run every N minutes
how to set cronjob for 2 days?
The test you want to perform is written in /bin/sh as:
[ $(date "+%u") = 5 ]
Which makes use of the test command (see man test). This is POSIX compliant and will work with any shell that your cron might run in (sh,bash,dash,ksh,zsh). The command date "+%u" returns the weekday from 1 to 7 (Sunday is 7). See man date for more info.
So your cronjob would look like:
0 0 13 * * [ $(date "+\%u") = 5 ] && command
Note that we have to escape the <percent>-character.
A % character in the command, unless escaped with a backslash (\), will be changed into newline characters, and all data after the first % will be sent to the command as standard input.
source: man 5 crontab
Unfortunately, CRON doesn't work the way you want
You can see all available options on below url
https://www.freeformatter.com/cron-expression-generator-quartz.html
So what you can do is the execute the cron on every 13th of the month but don't let the command run when its Friday
0 0 0 13 * ? * mybatchjob.sh
mybatchjob.sh
if [ `date +'%A'` = "Friday" ]; then
echo "Yep its Friday";
else
echo "Not Friday";
fi
This will make sure that the intended program only runs on Friday and the 13th

How can I create Cron Expression which works between particular times

I am working on a Cron Expression for a job that has to run on weekdays every 10 mins from 7.30 am to 8.20 am(inclusive).
The trigger used by me:-
0 30/10 7-9 ? * SUN,MON,TUE,WED,THU *
Issue is it works beyond 8.20 as well? Can we limit it to specific minutes or end time? like 7:30-8:20
Some things you cannot do in a single expression and you might consider to use two:
# Example of job definition:
# .--------------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
# This runs on 7:30, 7:40, 7:50
30/10 7 * * 1-5 command
# This runs on 8:00, 8:10, 8:20
0-20/10 8 * * 1-5 command
Another way you could attempt this is by using a test.
# Example of job definition:
# .--------------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
*/10 7,8 * * 1-5 testcmd && command
Where testcmd is an executable script that could look like:
#!/usr/bin/env bash
hours=$(date "+%H")
minutes=$(date "+%M")
(( hours == 7 && minutes >= 30)) || (( hours == 8 && minutes <= 20 ))
Other examples of this trick can be found here:
Cron expression to run every N minutes
How to schedule a Cron job to run 4th week of the year
how to set cronjob for 2 days?

cron at 15,55 and 35 every other hour

first are these cron anyway similar and if so which ones are redundant?
a) 15,35,55 * * * *
b) 15,35,55 */1 * * *
c) 15,35,55 0/1 * * *
What would be the cron to run at 35 and 15min/55min interchanged by an hour?
e.g
8am - 9am: 8:35am
9am - 10am: 9:15am and 9:55am
10am - 11am: 10:35am
11am - 12am: 11:15am and 11:55am
e.t.c
If you want to know what your cron is doing, then you can easily use crontab-guru to verify.
On your first question, yes the three examples are identical. The manual states the following :
man 5 crontab: Step values can be used in conjunction with ranges. Following a range with /<number> specifies skips of the
number's value through the range. For example, 0-23/2 can be used
in the 'hours' field to specify command execution for every other hour
(the alternative in the V7 standard is
0,2,4,6,8,10,12,14,16,18,20,22). Step values are also permitted
after an asterisk, so if specifying a job to be run every two hours,
you can use */2.
See the following examples:
# Example of job definition:
# .-------------------------- minute (0 - 59)
# | .----------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
15,35,55 * * * * command1
15,35,55 */1 * * * command2
15,35,55 0/1 * * * command3
15,35,55 0-23/1 * * * command4
So in the above example, command[1-4] will be executed at the same time, every hour on minute 15, 35 and 55
For your second question, it is best done this way :
# Example of job definition:
# .------------------------ minute (0 - 59)
# | .----------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr .
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
15 0/2 * * * command1
35,55 1/2 * * * command1
15 8/2 * * * command2
35,55 9/2 * * * command2
15 8-18/2 * * * command3
35,55 9-18/2 * * * command3
Here, command1 will execute on {00,02,04,06,...,22}:15 and {01,03,05,...,23}:{35,15}, command2 will execute on {08,10,...,22}:15 and {09,11,...,23}:{35,15} and command3 will execute on {08,10,...,18}:15 and {09,11,...,17}:{35,15}.

How can I specify time in CRON considering YEAR?

My task is to specify time in CRON considering YEAR field. How can i do it, or do u know any stuff which can help me on my linux server? thx
As indicated in earlier posts, you cannot indicate a year field, it is, however, possible to mimic it:
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
0 0 1 1 * [[ $(date "+\%Y") == 2020 ]] && command1
0 0 1 1 * (( $(date "+\%Y") % 3 == 0 )) && command2
0 0 1 1 * (( $(date "+\%Y") % 3 == 1 )) && command3
Here, command1 will run on the 2020-01-01T00:00:00, command2 will run every 3 years on the first of January at midnight, it will run so on 2019, 2022, 2025, ... . command3 does the same as command2 but has one year offset, i.e. 2020, 2023, 2026, ...
note: don't forget that you have to escape the <percent>-character (%) in your crontab file:
The "sixth" field (the rest of the line) specifies the command to be run. The entire command portion of the line, up to a newline or
a "%" character, will be executed by /bin/sh or by the shell specified in the SHELL variable of the cronfile. A "%" character in the command, unless escaped with a backslash (\), will be changed into newline characters, and all data after the first % will be sent to the command as standard input.
source: man 5 crontab
Crontab (5) file format has no YEAR field. You could try running a cron job #yearly (at 00:00 on New Year's day) which looks at the current year using date(1) and updates the current crontab file to one appropriate for the new year.
Standard cron doesn't support a year field, but it's worth noting that some implementations support an extended crontab format with a sixth year field, such as nnCron. Not every cron is created equal.
var task = cron.schedule('0 0 1 1 *', () => {
console.log('Printing this line 1ST JANUARY OF EVERY YEAR in the terminal');
});
It is work for considering YEAR field..
#mart7ini

Resources