我必须在每个月的第一个工作日设置cronjob,这意味着脚本应该在每个月的第一个工作日运行。
如果假设第一次工作是假期,那么脚本应该在第二个工作日运行。 例如:2015年1月1日是假日,然后脚本应该在2015年1月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在每个工作日运行你的脚本,你的脚本(或包装器)需要检查它是否是当月的第一个工作日(否则退出)。