I have to set the cronjob for 1st working day of every month which means the script should run on 1st working day of every month.
If suppose 1st working is an holiday then the script should run on the 2nd working day. For eg: Jan 1 2015 is holiday then the script should run on Jan 2 2015.
You need to combine two approaches: a) Use cron to run a job every Sunday at 9:00am. b) At the beginning of once_a_week , compute the date and extract the day of the month via shell, Python, C/C++, ... and test that is within 1 to 7, inclusive. If so, execute the real script; if not, exit silently.
It is a wildcard for every part of the cron schedule expression. So * * * * * means every minute of every hour of every day of every month and every day of the week .
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.
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 day d
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 day d
with 1=Monday and 7=Sunday.
if [ "$dow" -le 5 ] && grep -vq "$today" /path/holidays
The test "$dow" -le 5 ]
verifies that day d
is a weekday (Monday-Friday). The test grep -vq "$today" /path/holidays
verifies that day d
's date does not appear in the holidays
file. If both tests are true, then day d
is a work day and the then
clause is executed:
then workday=Yes; nworkdays=$((nworkdays+1))
The then
clause sets workday
to Yes
and also increments the count of workdays so far this month: nworkdays
else workday=
The else
clause sets workday
back to the empty string.
fi
fi
signals the end of the if
statement.
done
done
signifies the end of the for
loop.
[ "$workday" ] && [ "$nworkdays" -eq 1 ] && /path/command
The last loop in the for
statement was for today's date. Thus, if workday=Yes
after the loop ends, then today is a workday. Furthermore, if nworkdays=1
, then today is the first workday of the month. If both conditions are true, then your command /path/command
is executed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With