我需要你的帮助来构建一个 cron 作业,在每个月倒数第二个工作日运行。我可以按照下面所示执行 LW,但我不确定如何执行倒数第二个。我需要你的帮助和建议。
@MWE 好心地为我提供了一个可能的解决方案,但它似乎并不适用于所有测试场景。
code:
#!/bin/bash
date
WEEKDAY=$(date +%u)
# If detect the montday in 2 days.
if [ $(date +%d -d "2 day") -eq 1 ] && [ ${WEEKDAY} -lt 5 ] ; then
echo "This is the 2. last working day of the month"
# If detect the montday in 5 days.
elif [ $(date +%d -d "5 day") -eq 1 ] && [ ${WEEKDAY} -eq 5 ] ; then
echo "This is the 2. last working day of the month"
else
exit
fi
测试场景:我已将服务器上的系统日期修改为 2019 年 8 月 29 日(**这是系统上的倒数第二个工作日期)
调试模式下的脚本退出:
[oracle@rdbauroral01v ~]$ bash -x ./crontest.sh
+ date
Thu Aug 29 13:28:20 UTC 2019
++ date +%u
+ WEEKDAY=4
++ date +%d -d '2 day'
+ '[' 31 -eq 1 ']'
++ date +%d -d '5 day'
+ '[' 03 -eq 1 ']'
+ exit
感谢您的帮助。
答案1
就像在脚本中而不是在 crontab 中解决该问题的简单想法一样:
当明天 = 一个月的 1 时,一个月的最后一天永远是这一天。
这意味着:让我们从纪元秒数中取出当前日期,并添加 24 小时。然后让我们取出它是月份中的哪一天:
TIMESTAMP=$(date +%s)
TIMESTAMP_TOMORROW=$(( $TIMESTAMP + 86400 ))
计算明天的月份日期:
DAYOFMONTH=$(date --date="@${TIMESTAMP_TOMORROW}" +%e)
如果 DAYOFMONTH == 1,则今天是该月的最后一天。然后执行您想要的操作。如果不是 == 1,则退出。
您可以在这里找到替代方案:https://stackoverflow.com/questions/6139189/cron-job-to-run-on-the-last-day-of-the-month
TODAY=`date +%d`
TOMORROW=`date +%d -d "1 day"`
# See if tomorrow's day is less than today's
if [ $TOMORROW -lt $TODAY ]; then
echo "This is the last day of the month"
# Do stuff...
fi
或者:
0 23 28-31 * * [ `/bin/date -d +1day +\%d` -eq 1 ] && myscript.sh
最后但并非最不重要的一点。将 $(( $TIMESTAMP + 86400 * 2 )) 乘以 2,得到倒数第二天。
或者:
TOMORROW=$(date +%d -d "2 day")
或者:
[ $(/bin/date -d +2day +\%d) -eq 1 ]
答案2
2. 取出每月的最后一个工作日。%u 从星期一开始作为第一天。%w 从星期日开始。
- 最后一个工作日通常是星期四。所以是第四个工作日。我们现在必须考虑未来 6 天。-> 意思是,本月的最后一个工作日必须在本月第五天之前。
WEEKDAY=$(date +%u) TOMORROW=$(date +%d -d "5 day") if [ ${WEEKDAY} -eq 4 ] && [ $TOMORROW -lt 5 ]; then echo "This is the 2. last working day of the month" fi
答案3
在 crontab 中,您可以将执行限制在工作日和月日。两者结合是一个好的开始。因此,您可以确保脚本仅在工作日运行。在月日感知的二月(28 天等)或仅 30 天。它不会在每个月的 31 日结束!因此,为了安全起见,也许可以使用 20-31 天。
field allowed values
----- --------------
minute 0-59
hour 0-23
day of month 1-31
month 1-12 (or names, see below)
day of week 0-7 (0 or 7 is Sunday, or use names)
Crontabentry 喜欢:
0 0 20-31 * 1-5 ./scriptname
这部分很容易找出,第二个、第三个或第四个是星期几。为什么?脚本仅在工作日由 crontab 运行。所以我们不必关心星期六或星期日。另一种方法是,我们可以检查星期几 $(date +%u) 是否在 1-5 之间。这是工作日。
代码现在很简单:
如果 2 天后是该月的第一天... 则是倒数第二个工作日。但是,周六和周日呢?
你现在需要一个案例。从星期一到星期四总是一个工作日。所以规则是,如果它在 2 天后的第一个月日,它就是第二个工作日。只有星期五必须是 5 天后的月初才能成为第二个工作日。或者一个月的第一天必须是星期二。
WEEKDAY=$(date +%e)
# 1. If detect the montday in 2 days.
if [ $(date +%d -d "2 day") -eq 1 ] && [ ${WEEKDAY} -lt 5 ] ; then
echo "This is the 2. last working day of the month"
# 1. If detect the montday in 5 days.
elif [ $(date +%d -d "5 day") -eq 1 ] && [ ${WEEKDAY} -eq 5 ]
echo "This is the 2. last working day of the month"
else
exit
fi
希望我没有错过任何东西。
答案4
请尝试以下文章来更好地理解 cron 中允许的表达式类型,
具体来说,如果您在“月份中的某天”指定为“28W” --> 它会在 28 日执行,或者如果 28 日是星期六/星期日,它会在最近的工作日执行(如果 28 日是星期六,那么它会在 27 日执行;如果 28 日是星期日,那么它会在 29 日执行)
參考文獻:http://www.brightxpress.com/user/appendix/cron_expressions.htm