Set Cron Job for 1st working day of every month in Shell Scripting
First, run the date command:
$ date '+%x'
> 12/29/2014
%x tells date to display today's date in the format of the current locale. Using that exact same format, put a list of holidays in a file called holidays. For example:
$ cat holidays
> 01/01/2015
> 07/04/2015
Next, create the following shell script:
#!/bin/sh
dom=$(date '+%d') # 01-31, day of month
year=$(date '+%Y') # four-digit year
month=$(date '+%m') # two-digit month
nworkdays=0
for d in $(seq 1 $dom)
do
today=$(date -d "$year-$month-$d" '+%x') # locale's date representation (e.g. 12/31/99)
dow=$(date -d "$year-$month-$d" '+%u') # day of week: 1-7 with 1=Monday, 7=Sunday
if [ "$dow" -le 5 ] && grep -vq "$today" /path/holidays
then
workday=Yes
nworkdays=$((nworkdays+1))
else
workday=
fi
done
[ "$workday" ] && [ "$nworkdays" -eq 1 ] && /path/command
How do I run a script for 1st working day of every month in cron?
First, run the date
command:
$ date '+%x'
12/29/2014
%x
tells date to display today's date in the format of the current locale. Using that exact same format, put a list of holidays in a file called holidays
. For example:
$ cat holidays
01/01/2015
07/04/2015
Next, create the following shell script:
#!/bin/sh
dom=$(date '+%d') # 01-31, day of month
year=$(date '+%Y') # four-digit year
month=$(date '+%m') # two-digit month
nworkdays=0
for d in $(seq 1 $dom)
do
today=$(date -d "$year-$month-$d" '+%x') # locale's date representation (e.g. 12/31/99)
dow=$(date -d "$year-$month-$d" '+%u') # day of week: 1-7 with 1=Monday, 7=Sunday
if [ "$dow" -le 5 ] && grep -vq "$today" /path/holidays
then
workday=Yes
nworkdays=$((nworkdays+1))
else
workday=
fi
done
[ "$workday" ] && [ "$nworkdays" -eq 1 ] && /path/command
where /path/command
is replaced by whatever command you want to run on the first working day of the month. Also, replace /path/holidays
with the correct path to your holidays
file.
Lastly, tell cron to run the above script every day. Your command
will be executed only on the first working day of the month.
How it works
Let's look at the core of the script:
for d in $(seq 1 $dom); do
This starts a loop running the variable
d
from 1 to the current day-of-the-month.today=$(date -d "$year-$month-$d" '+%x') # locale's date representation (e.g. 12/31/99)
This sets
today
to the datestring for the dayd
of this month and year.dow=$(date -d "$year-$month-$d" '+%u') # day of week: 1-7 with 1=Monday, 7=Sunday
This sets
dow
to the day-of-the-week for dayd
with 1=Monday and 7=Sunday.if [ "$dow" -le 5 ] && grep -vq "$today" /path/holidays
The test
"$dow" -le 5 ]
verifies that dayd
is a weekday (Monday-Friday). The testgrep -vq "$today" /path/holidays
verifies that dayd
's date does not appear in theholidays
file. If both tests are true, then dayd
is a work day and thethen
clause is executed:then workday=Yes; nworkdays=$((nworkdays+1))
The
then
clause setsworkday
toYes
and also increments the count of workdays so far this month:nworkdays
else workday=
The
else
clause setsworkday
back to the empty string.fi
fi
signals the end of theif
statement.done
done
signifies the end of thefor
loop.[ "$workday" ] && [ "$nworkdays" -eq 1 ] && /path/command
The last loop in the
for
statement was for today's date. Thus, ifworkday=Yes
after the loop ends, then today is a workday. Furthermore, ifnworkdays=1
, then today is the first workday of the month. If both conditions are true, then your command/path/command
is executed.
Cron - How to run a job on the first weekday after a specific day of the month?
You can't define such logic in cron
and the usual way is to add it in to the script you want to run. So run the script every day like this:
0 0 * * * /path/to/script.sh
and add inside
if [ "$(date +%d%m)" == "0101" ]
then rm -f /var/run/flag
fi
if [ $(date +%d) -ge 12 ] && [ $(date +%w) -gt 0 ] && [ $(date +%w) -lt 6 ] && [ ! -f /var/run/flag ]
then <do the work>
touch /var/run/flag
fi
exit
Also you should take care to run only once (as far as I understand)
schedule a cron job to run on 1st, 2nd, and 3rd tuesday of every month
An alternative would be to create main-script to run every Tuesday, verify that Tuesday is and that hour is accordingly invokes the appropriate secondary script.
0 7,9 * * 2 wget -q -O /dev/null http://site.com/main-script
I hope that is helpful.
Greetings.
How to schedule to run first Sunday of every month
You can put something like this in the crontab
file:
00 09 * * 7 [ $(date +\%d) -le 07 ] && /run/your/script
The date +%d
gives you the number of the current day, and then you can check if the day is less than or equal to 7. If it is, run your command.
If you run this script only on Sundays, it should mean that it runs only on the first Sunday of the month.
Remember that in the crontab
file, the formatting options for the date
command should be escaped.
How to run cronjob on every month first friday?
This is because when you specify a day of month and day of week, cron will execute the job when EITHER of those constraints are true. From the man page for crontab (5):
Note: The day of a command's execution can be specified by two fields —
day of month, and day of week. If both fields are restricted (i.e.,
aren't *), the command will be run when either field matches the cur‐
rent time. For example,
``30 4 1,15 * 5'' would cause a command to be run at 4:30 am on the 1st
and 15th of each month, plus every Friday.
There isn't a direct way in cron to do what you want, but cron : how to schedule to run first Sunday of every month describes a workaround by using cron to run your script e.g. every Friday and then calculating in the script if the day of month is in the range 1-7, and only continuing when that is the case.
In response to the comment about using 5 rather than Fri to specify day of week: using Fri is OK, as the man page says:
Months or days of the week can be specified by name.
How to schedule a cron for the first Thursday of every month
the answer:
0 15 * * 4 [ $(date +\%d) -le 7 ] && command
the explanation:
First of all you need to realize that the first Thursday of the month will always have a day of the month that is in the set {1,2,3,4,5,6,7}
. That is simply because there are only 7 days in a week. And thus the first Thursday cannot be have a day that is bigger then 7. The same holds evidently for any other weekday such as Tuesday or Saturday.
The command that cron will execute consists of two parts:
[ $(date "+\%d") -le 7 ]
: This is a simple test that checks if the day of the month is smaller than 7. It essentially checks if we are in the first week of the month. The commanddate -d "+%d"
returns the day of the month as a two-digit number (01,02,03,...,31
) and is a string. Thetest
command, here written in an alternative form with square brackets[ ... ]
does a check to see if the integer comming fromdate
is smaller then or equal to 7. You can read more on this when typingman test
in a terminal.command
: this is the command that is going to be executed if the previoustest
is successful. I.e. if we are in the first week of the month. The reason why this will only execute if thetest
command is successful, is because of the&&
. A command of the formcmd1 && cmd2
will executecmd1
and only when that one is successful will it executecmd2
.
So since we now have the command, we can now build our crontab file. With a bit more comments (parts starting with #
, you can write it as:
# 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 15 * * 4 [ $(date +\%d) -le 07 ] && command
The above means, execute the above command at minute 0 of the 15th hour of any Thursday. And since the command contains the test for the first week, it will only run on the first Thursday of the month.
Schedule Cron to skip first Saturday of every month
Since there seem to be no option in Cron.
I'm going with script for the above need.
**if [ $(date +%d) -le 7 ] && [ $(date +%u) -eq 1 ] ;**
[ $(date +%d) -le 7 ]
- Checks if the days fall in first 7 days of month
[ $(date +%u) -eq 6 ]
- Checks if day is equal to Saturday
Thanks.
Related Topics
How to Enable Hocr Font Info in Tesseract 4
Linux/Cygwin Recursively Copy File Change Extension
Getting Uptime or Downtime of Systemd Process Using Systemctl
Analyze Memory with Crash with Kdump
How to Find All Immediate Sub-Directories of The Current Directory on Linux
Why Does Munmap Needs a Length as Parameter
Sshfs, Linux - How to Mount with Read-Only Access
Xmonad: Spawnon Workspace That Had Focus When Spawn Key Was Pressed
Generating a Comprehensive Callgraph Using Gcc & Egypt
How to Change File Extension in Linux Shell Script
Best Linux Filesystem Filter Option
Can't Install Using Yum in Rhel 7.1
Re-Stream a Mpeg2 Ts Pal Stream with Crtmpserver
How to Mmap() a Large File Without Risking The Oom Killer
Kill Bash Script Foreground Children When a Signal Comes
How to Change Core Pattern Only for a Particular Application