Bash 如何在cron中为每个月的第一个工作日运行脚本?
我必须将cronjob设置为每个月的第一个工作日,这意味着脚本应该在每个月的第一个工作日运行 如果假设第一个工作日是假日,那么脚本应该在第二个工作日运行。Bash 如何在cron中为每个月的第一个工作日运行脚本?,bash,unix,cron,Bash,Unix,Cron,我必须将cronjob设置为每个月的第一个工作日,这意味着脚本应该在每个月的第一个工作日运行 如果假设第一个工作日是假日,那么脚本应该在第二个工作日运行。 例如:2015年1月1日是假日,那么脚本应该在2015年1月2日运行。Cron没有假日日历的概念,也没有添加此类概念的挂钩。悲伤,但真实。您将需要实现您自己的假日日历(或者很明显,找到一个,但不是在cron中)。然后,您可以将cron设置为在每个工作日运行脚本,您的脚本(或包装器)将需要检查它是否是当前月份的第一个工作日(否则退出)。首先,运
例如:2015年1月1日是假日,那么脚本应该在2015年1月2日运行。Cron没有假日日历的概念,也没有添加此类概念的挂钩。悲伤,但真实。您将需要实现您自己的假日日历(或者很明显,找到一个,但不是在cron中)。然后,您可以将cron设置为在每个工作日运行脚本,您的脚本(或包装器)将需要检查它是否是当前月份的第一个工作日(否则退出)。首先,运行
date
命令:
$ date '+%x'
12/29/2014
%x
告诉date以当前区域设置的格式显示今天的日期。使用完全相同的格式,将假日列表放入名为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每天运行上面的脚本。您的命令将仅在每月的第一个工作日执行
工作原理
让我们看一下脚本的核心:
表示d,单位为美元(seq 1$dom);执行
这将启动一个循环,运行变量d
,从1到当月的当前日期
today=$(日期-d“$year-$month-$d”'+%x')#区域设置的日期表示法(例如1999年12月31日)
这将today
设置为本月和本年日期d
的日期字符串
dow=$(日期-d“$year-$month-$d”+%u”)#一周中的一天:1-7天,其中1=周一,7=周日
这将d
天的dow
设置为一周中的某一天,其中1=周一,7=周日
if[“$dow”-le 5]&grep-vq“$today”/path/假日
测试“$dow”-le 5]
验证d
是工作日(周一至周五)。测试grep-vq“$today”/path/holidays
验证dayd
的日期是否未出现在holidays
文件中。如果两个测试均为真,则第天d
为工作日,执行then
子句:
然后workday=Yes;nworkdays=$((nworkdays+1))
then
子句将workday
设置为Yes
,并增加本月迄今为止的工作日数:nworkdays
else workday=
else
子句将workday
设置回空字符串
fi
fi
表示if
语句结束
done
done
表示for
循环的结束
[“$workday”]&&&[“$nworkdays”-等式1]&&&/path/command
for
语句中的最后一个循环是今天的日期。因此,如果循环结束后workday=Yes
,那么今天就是工作日。此外,如果nworkdays=1
,则今天是当月的第一个工作日。如果这两个条件都为真,则执行命令/path/command
也许你可以使用一个智能作业(程序)来检查今天是否是假日,如果不是假日,则让代码运行你的作业。使用cron,您可以安排智能作业每天运行。此外,这可能很有趣:没有复制粘贴示例。首先,您需要为自己选择的假日定义构建或购买假日日历。然后,您需要编写一个使用该日历的脚本。我有一个查询,这里**if[“$dow”-le 5]&&grep-vq“$today”/path/holidays**我们必须在这里声明假日日历的路径正确??除此之外,我得到了所有信息,谢谢@John1024@Shirchabayshan只要用正确的路径替换/path/
。例如,如果假日文件是/etc/holidays
,那么使用:如果[“$dow”-le5]&&grep-vq“$today”/etc/holidays
我有一个查询@John1024,假设dom=31 today=12/31/2014,如果[“$dow”-le5]&&grep-vq“$today”/path/holidays(自12月31日不是假日以来,该条件将为真)它将进入循环。workday=Yes nworkdays=1此处[“$workday”]&&&[“$nworkdays”-eq 1]&&&&/path/command(条件为真),但我怀疑这怎么会是第一个工作日?该条件在所有工作日内均为真。。。在第一个工作日之后,脚本不应在每次进入循环时运行…@shirchabaysan,nworkdays
递增1:nworkdays=$((nworkdays+1))
。这意味着在2014年1月1日,nworkdays=1
、2014年2月1日,nworkdays=2
、2014年12月31日,nworkdays=22
(假设圣诞节被标记为假日)。如果nworkdays=22
,则条件将为false,并且/path/command
将不会运行。