如何在 bash 中验证 crontab 调度值

问题描述 投票:0回答:1

我正在编写一个 bash 脚本,它接受与 crontab 相同的调度值(星期几、月份等)。

到目前为止,我的脚本能够接受每个值的星号(

*
),或特定值的整数。但是,我的脚本还需要支持范围 (
-
)、列表 (
,
) 和步长值 (
/
),如此处所述。

这是我的使用说明:

function print_usage() {
  echo "Usage:  `basename $0` -a APPLICATION [-D DAY_OF_WEEK] [-M MONTH] [-d DAY_OF_MONTH] [-H HOUR] [-m MINUTE] [-u]"
  echo "Options:"
  echo " -a APPLICATION    EMR application (application:container)"
  echo " -D DAY_OF_WEEK    day of the week (0 - 7) (Sunday=0 or 7)"
  echo " -M MONTH          month (1 - 12)"
  echo " -d DAY_OF_MONTH   day of the month (1 - 31)"
  echo " -H HOUR           hour (0 - 23)"
  echo " -m MINUTE         minute (0 - 59)"
  echo " -u                uninstall the CRON job(s) for the application"
  exit 0
}

这些是我当前的验证:

if [[ ! $DAY_OF_WEEK =~ ^(0?[0-7]|\*)$ ]]; then
  echo "ERROR: DAY_OF_WEEK parameter must be a positive integer (0 - 7) (Sunday=0 or 7) or an asterisk"
  exit 1
fi
if [[ ! $MONTH =~ ^((0?[1-9]|1[0-2])|\*)$ ]]; then
  echo "ERROR: MONTH parameter must be a positive integer (1 - 12) or an asterisk"
  exit 1
fi
if [[ ! $DAY_OF_MONTH =~ ^((0?[1-9]|[1-2][0-9]|3[0-1])|\*)$ ]]; then
  echo "ERROR: DAY_OF_MONTH parameter must be a positive integer (1 - 31) or an asterisk"
  exit 1
fi
if [[ ! $HOUR =~ ^((0?[0-9]|1[0-9]|2[0-3])|\*)$ ]]; then
  echo "ERROR: HOUR parameter must be a positive integer (0 - 23) or an asterisk"
  exit 1
fi
if [[ ! $MINUTE =~ ^((0?[0-9]|[1-5][0-9])|\*)$ ]]; then
  echo "ERROR: MINUTE parameter must be a positive integer (0 - 59) or an asterisk"
  exit 1
fi

我不太确定如何开始支持调度参数的范围、列表和步长值。现在,如果您为分钟参数指定

15
,它将在每小时 15 分钟运行脚本 - 但无法每 15 分钟指定一次,除非我支持像
*/15
这样的参数值。

regex bash cron
1个回答
0
投票

您正在编写一个操作文本的工具。 shell 是一种操作(创建/销毁)文件和进程以及对其他工具的调用顺序的工具。用于通用文本操作的强制性 POSIX(在所有 Unix 机器上可用)工具是 awk。因此,要使用 shell 操作文本,正确的方法是编写 awk 脚本来进行文本操作,然后 shell 脚本主要只是调用 awk 来解释 awk 脚本。

如果需要,您可以将 awk 输出读入 bash 标量变量或数组,以便稍后在 shell 脚本中使用它们。如果您需要使用 shell 执行其他操作,但如果您只是操作文本,那么只需在 awk 中完成所有操作即可。

以下是如何扩展数字和字符串范围的开始:

$ cat tst.sh
#!/usr/bin/env bash

expand() {
    awk -v dowNums="$1" -v monthNums="$2" -v dowStrs="$3" -v monthStrs="$4" '
        BEGIN {
            printf "dowNums\t\"%s\"\t-> \"%s\"\n", dowNums, expandNums(dowNums,1,7)
            printf "monthNums\t\"%s\"\t-> \"%s\"\n", monthNums, expandNums(monthNums,1,12)
            printf "dowStrs\t\"%s\"\t-> \"%s\"\n", dowStrs, expandStrs(dowStrs,"Mon Tue Wed Thu Fri Sat Sun")
            printf "monthStrs\t\"%s\"\t-> \"%s\"\n", monthStrs, expandStrs(monthStrs,"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")
        }

        function expandNums(spec,minBeg,maxEnd, \
                                beg,end,range,i,list) {
            if ( spec == "" ) {
                return
            }

            if ( spec ~ /^[^*-]+$/ ) {
                beg = spec
                end = beg
            }
            else if ( spec == "*" ) {
                beg = minBeg
                end = maxEnd
            }
            else if ( split(spec,range,"-") == 2 ) {
                beg = range[1]
                end = range[2]
            }

            if ( ( beg+0 == beg ) &&
                 ( end+0 == end ) &&
                 ( beg <= end ) &&
                 ( (minBeg <= beg) && (beg <= maxEnd) ) &&
                 ( (minBeg <= end) && (end <= maxEnd) ) )
            {
                for ( i=beg; i<=end; i++ ) {
                    list = list i (i<end ? OFS : "")
                }
            }

            if ( list == "" ) {
                printf "Bad spec: \"%s\"\n", spec |"cat>&2"
            }

            return list
        }

        function expandStrs(spec,vals, \
                                idxs2vals,vals2idxs,minBeg,maxEnd,beg,end,range,i,list) {
            if ( spec == "" ) {
                return
            }

            minBeg = 1
            maxEnd = split(vals,idxs2vals," ")
            for ( i in idxs2vals) {
                vals2idxs[idxs2vals[i]] = i
            }

            if ( spec ~ /^[^*-]+$/ ) {
                beg = ( spec in vals2idxs ? vals2idxs[spec] : "" )
                end = beg
            }
            else if ( spec == "*" ) {
                beg = minBeg
                end = maxEnd
            }
            else if ( split(spec,range,"-") == 2 ) {
                beg = ( range[1] in vals2idxs ? vals2idxs[range[1]] : "" )
                end = ( range[2] in vals2idxs ? vals2idxs[range[2]] : "" )
            }

            if ( ( beg+0 == beg ) &&
                 ( end+0 == end ) &&
                 ( beg <= end ) &&
                 ( (minBeg <= beg) && (beg <= maxEnd) ) &&
                 ( (minBeg <= end) && (end <= maxEnd) ) )
            {
                for ( i=beg; i<=end; i++ ) {
                    list = list idxs2vals[i] (i<end ? OFS : "")
                }
            }

            if ( list == "" ) {
                printf "Bad spec: \"%s\"\n", spec |"cat>&2"
            }

            return list
        }
    '
}

echo "Varying day of week number specs"
expand '4'      ''      ''              ''
expand '3-6'    ''      ''              ''
expand '*'      ''      ''              ''

echo ""
echo "Varying month number specs"
expand ''       '4'     ''              ''
expand ''       '3-6'   ''              ''
expand ''       '*'     ''              ''

echo ""
echo "Varying day of week abbreviation specs"
expand ''       ''      'Tue'           ''
expand ''       ''      'Wed-Fri'       ''
expand ''       ''      '*'             ''

echo ""
echo "Varying month abbreviation specs"
expand ''       ''      ''              'Apr'
expand ''       ''      ''              'Mar-Jun'
expand ''       ''      ''              '*'

$ ./tst.sh
Varying day of week number specs
dowNums "4"     -> "4"
monthNums       ""      -> ""
dowStrs ""      -> ""
monthStrs       ""      -> ""
dowNums "3-6"   -> "3 4 5 6"
monthNums       ""      -> ""
dowStrs ""      -> ""
monthStrs       ""      -> ""
dowNums "*"     -> "1 2 3 4 5 6 7"
monthNums       ""      -> ""
dowStrs ""      -> ""
monthStrs       ""      -> ""

Varying month number specs
dowNums ""      -> ""
monthNums       "4"     -> "4"
dowStrs ""      -> ""
monthStrs       ""      -> ""
dowNums ""      -> ""
monthNums       "3-6"   -> "3 4 5 6"
dowStrs ""      -> ""
monthStrs       ""      -> ""
dowNums ""      -> ""
monthNums       "*"     -> "1 2 3 4 5 6 7 8 9 10 11 12"
dowStrs ""      -> ""
monthStrs       ""      -> ""

Varying day of week abbreviation specs
dowNums ""      -> ""
monthNums       ""      -> ""
dowStrs "Tue"   -> "Tue"
monthStrs       ""      -> ""
dowNums ""      -> ""
monthNums       ""      -> ""
dowStrs "Wed-Fri"       -> "Wed Thu Fri"
monthStrs       ""      -> ""
dowNums ""      -> ""
monthNums       ""      -> ""
dowStrs "*"     -> "Mon Tue Wed Thu Fri Sat Sun"
monthStrs       ""      -> ""

Varying month abbreviation specs
dowNums ""      -> ""
monthNums       ""      -> ""
dowStrs ""      -> ""
monthStrs       "Apr"   -> ""
Bad spec: "Apr"
dowNums ""      -> ""
monthNums       ""      -> ""
dowStrs ""      -> ""
monthStrs       "Mar-Jun"       -> ""
Bad spec: "Mar-Jun"
dowNums ""      -> ""
monthNums       ""      -> ""
dowStrs ""      -> ""
monthStrs       "*"     -> "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
© www.soinside.com 2019 - 2024. All rights reserved.