如何在cron中每个月的第一个工作日运行脚本?

时间:2014-12-30 05:29:17

标签: bash unix cron

我必须在每个月的第一个工作日设置cronjob,这意味着脚本应该在每个月的第一个工作日运行

如果假设第一次工作是假期,那么脚本应该在第二个工作日运行。 例如:2015年1月1日是假日,然后脚本应该在2015年1月2日运行。

2 个答案:

答案 0 :(得分:4)

首先,运行date命令:

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

%x告诉日期以当前区域设置的格式显示今天的日期。使用完全相同的格式,将假日列表放在名为holidays的文件中。例如:

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

接下来,创建以下shell脚本:

#!/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

其中/path/command将替换为您希望在该月的第一个工作日运行的任何命令。另外,将/path/holidays替换为holidays文件的正确路径。

最后,告诉cron每天运行上面的脚本。您的command只会在该月的第一个工作日执行。

如何运作

让我们看一下脚本的核心:

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

    这会启动一个循环,将变量d从1运行到当前的每月。

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

    这会将today设置为此月和日的d天的日期字符串。

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

    这会将dow设置为第d天的星期几,其中1 =星期一,7 =星期日。

  • if [ "$dow" -le 5 ] && grep -vq "$today" /path/holidays

    测试"$dow" -le 5 ]验证当天d是工作日(周一至周五)。测试grep -vq "$today" /path/holidays验证d文件中没有出现holidays天的日期。如果两个测试均为真,则第d天为工作日,并执行then子句:

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

    then条款将workday设置为Yes,并且还会增加本月到目前为止的工作日数:nworkdays

  • else workday=

    else子句将workday设置回空字符串。

  • fi

    fi表示if声明结束。

  • done

    done表示for循环结束。

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

    for声明中的最后一个循环是今天的日期。因此,如果循环结束后workday=Yes,那么今天就是工作日。此外,如果是nworkdays=1,则今天是该月的第一个工作日。如果两个条件均为真,则执行命令/path/command

答案 1 :(得分:1)

Cron没有假日日历的概念,也没有添加这样一个概念的钩子。悲伤,但是真的。您需要实现自己的假日日历(或者找一个,显然,但不是在cron中)。然后你可以设置cron在每个工作日运行你的脚本,你的脚本(或包装器)需要检查它是否是当月的第一个工作日(否则退出)。