How to run a script for the 1st working day of every month in cron?

I have to set cronjob for the 1st working day of each month, which means the script should work on the 1st working day of each month .

If we assume that the 1st work is a holiday, then the script should work on the 2nd working day. For example: January 1, 2015 is a holiday, and the script is January 2, 2015.

+5
source share
2 answers

First run the date command:

 $ date '+%x' 12/29/2014 

%x specifies the date to display today's date in the current locale format. Using this exact format , put the list of holidays in a file called holidays . For instance:

 $ cat holidays 01/01/2015 07/04/2015 

Then 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 date representation (eg 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 any command that you want to run on the first business day of the month. Also, replace /path/holidays with the correct path to your holidays file.

Finally, 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

Look at the core script:

  • for d in $(seq 1 $dom); do

    Starts a cycle with variable d from 1 to the current day of the month.

  • today=$(date -d "$year-$month-$d" '+%x') # locale date representation (eg 12/31/99)

    This sets today to the end date for day d this month and year.

  • dow=$(date -d "$year-$month-$d" '+%u') # day of week: 1-7 with 1=Monday, 7=Sunday

    This sets the dow on 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 ] checks that day d is a weekday (from Monday to Friday). The grep -vq "$today" /path/holidays test grep -vq "$today" /path/holidays checks that the day d date is not displayed in the holidays file. If both tests are true, then day d is the working day, and then condition is satisfied:

  • then workday=Yes; nworkdays=$((nworkdays+1))

    The offer then sets workday to Yes , and also increases the number of working days this month: nworkdays

  • else workday=

    The else clause sets workday back to the empty string.

  • fi

    fi signals the end of the if .

  • done

    done means the end of the for loop.

  • [ "$workday" ] && [ "$nworkdays" -eq 1 ] && /path/command

    The last for loop was for today's date. Thus, if workday=Yes after the end of the cycle, then today is the working day. In addition, if nworkdays=1 , then today is the first working day of the month. If both conditions are true, your /path/command is executed.

+3
source

Cron has no idea about the holiday calendar and any kind of hooks to add such a concept. Sad but true. You will need to implement your own holiday calendar (or find it, obviously, but not in cron). And then you can set cron to run your script on every weekday, and your script (or wrapper) will need to check if this is the first working day of the current month (otherwise exit).

+1
source

Source: https://habr.com/ru/post/1210083/


All Articles