抽象的

抽象的

我读到了一份在该月最后一天安排脚本的说明:

笔记:
精明的读者可能想知道如何设置在每个月的最后一天执行的命令,因为您无法设置涵盖每个月的 dayofmonth 值。这个问题一直困扰着 Linux 和 Unix 程序员,并催生了相当多不同的解决方案。常见的方法是添加一个 if-then 语句,使用 date 命令检查明天的日期是否为 01:

00 12 * * * if [`date +%d -d tomorrow` = 01 ] ; then ; command1

它会在每天中午 12 点检查是否是该月的最后一天,如果是,则 cron 运行该命令。

在此输入图像描述

怎样[`date +%d -d tomorrow` = 01 ]运作?
表述正确吗then; command1

答案1

抽象的

正确的代码应该是:

#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"

调用这个脚本end_of_month.sh,在 cron 中的调用很简单:

00 12 28-31 * * /path/to/script/end_of_month.sh command

这将仅在第 28、29、30 和 31 天运行脚本end_of_month(内部将检查该天是否为该月的最后一天)。无需在任何其他日期检查月末。

旧帖子。

这是 Richard Blum、Christine Bresnahan 所著的《Linux Command Line and Shell Scripting Bible》一书的引文,第 442 页,第三版,John Wiley & Sons ©2015。

是的,这就是它所说的,但这是错误的/不完整的:

  • 缺少结束语fi
  • [和 以下之间需要空格`
  • 这是强烈地建议使用 $(...) 而不是`…`.
  • 使用引号很重要扩展喜欢"$(…)"
  • ;后面还有一个补充then

我怎么知道? (好吧,根据经验☺)但你可以尝试外壳检查。粘贴书中的代码(星号后面),它将显示上面列出的错误以及“missing shebang”。 Shellcheck 中没有任何错误的脚本是这样的:

#!/bin/sh if [ "$(date +%d -d tomorrow)" = 01 ] ; then script.sh; fi

该网站之所以有效,是因为编写的内容是“shell 代码”。这是一种适用于许多 shell 的语法。

shellcheck 没有提到的一些问题是:

  • 假设 date 命令是 GNU date 版本。带有-d接受tomorrow作为值的选项的选项(busybox 有一个 -d 选项,但不理解明天,BSD 有一个-d选项,但与时间的“显示”无关)。

  • 最好设置一下格式所有选项date -d tomorrow +'%d'

  • cron 启动时间始终采用当地时间,如果设置或未设置 DST(夏令时),这可能会使一项作业比确切的天数提前或晚 1 小时启动。

我们完成的是一个可以用 cron 调用的 shell 脚本。我们可以进一步修改脚本以接受要执行的程序或命令的参数,如下所示(最后是正确的代码):

#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"

调用这个脚本end_of_month.sh,在 cron 中的调用很简单:

00 12 28-31 * * /path/to/script/end_of_month.sh command

这将仅在第 28、29、30 和 31 天运行脚本end_of_month(内部将检查该天是否为该月的最后一天)。无需在任何其他日期检查月末。

确保包含正确的路径。 cron 内的 PATH 不会(不太可能)与用户 PATH 相同。

请注意,有月末脚本经测试(如下所示)可以调用许多其他实用程序或脚本。

这也将避免 cron 使用完整命令行生成的额外问题:

  • Cron 会在任何一个命令行上分割命令行,%即使用'or引用"(这里只有 a\有效)。这是 cron 作业失败的常见方式。

您可以end_of_month.sh通过使用 faketime 测试脚本来测试脚本在某个日期是否正常工作(无需等到月底才发现它不起作用):

$ faketime 2018/10/31 ./end_of_month echo "Command will be executed...."
Command will be executed....

答案2

假设语法错误已修复,并且命令稍微重新编写以变得不那么冗长:

00 12 28-31 * * [ "$( date -d tomorrow +\%d )" != "01" ] || command1

运行该程序date +%d -d tomorrow(假设date使用的是 GNU)以获取两位数形式的明天日期。如果号码不是01,那么今天不是该月的最后一天。在这种情况下,测试成功并且command1不是被执行。该作业在可能是该月最后一天的中午运行。

原来的命令:

00 12 * * * if [`date +%d -d tomorrow` = 01 ] ; then ; command1

这有几个问题:

  • 后面没有空格[
  • 直接;then.
  • %在 cron 作业规范中很特殊,必须转义为\%(请参阅man 5 crontab)。
  • fi最后没有与 相匹配的决赛if

答案3

要安排每个月的最后一天,您可以尝试:0 0 15,L * *

答案4

在你的 crontab 中

00 01 * * * [ $(date +\%d) -eq $(date \-d "-$(date +\%d) days month" +\%d) ] && /path/to/script.sh

以上将在该月最后一天凌晨 1 点运行。

相关内容