脚本在 Y 分钟内每 X 分钟重复一次“if”语句,如果不成立则失败

脚本在 Y 分钟内每 X 分钟重复一次“if”语句,如果不成立则失败

“autorep”和“sendevent”命令特定于 Autosys,但我必须运行的脚本如下:

if autorep -g GLOBAL_VARIABLE |grep " 0 " >/dev/null
 then 
  sendevent -E SET_GLOBAL -G "YES"

 else
  sleep 2
fi

如何循环此脚本直到 GLOBAL_VARIABLE = 0 或 20 分钟(以先到者为准)?

我正在考虑 for 循环,但希望得到一些指导。

autorep 命令的输出:

Global Name                                                      Value                                                                                                Last Changed
________________________________________________________________ ____________________________________________________________________________________________________ ____________________
GLOBAL_VARIABLE                                                        Y                                                                                                    12/15/2020 00:00:01

如果 GLOBAL_VARIABLE 的值不为 0,我需要脚本休眠 2 分钟,然后重试。如果 20 分钟结束时的值不是 0,则脚本应退出 1。

答案1

将其包装在一个while循环中,除了测试命令是否有效之外,还添加一个迭代计数或经过时间的测试。假设您正在测试的命令是正确的,这应该可以在 Bash 或标准 shell 中运行:

#!/bin/sh
elapsed=0
delay=2
timeout=$(( 20 * 60 ))
success=0
while true; do
    if autorep -g GLOBAL_VARIABLE |grep " 0 " >/dev/null; then
        success=1
        break
    fi
    if [ "$elapsed" -ge "$timeout" ]; then
        break
    fi 
    sleep "$delay"
    elapsed=$(( elapsed + delay ))
done
if [ "$success" = 1 ]; then
    echo "the command succeeded after waiting "$elapsed" seconds"
else
    echo "the command never succeeded within '$elapsed' seconds"
fi

delay单位timeout是秒,所以 20*60 = 1200 秒就是 20 分钟。

这仅考虑了睡眠时间,因此如果autorep需要花费大量时间才能完成,它将被关闭。在 Bash 中,您可以用来$SECONDS获取自脚本启动以来的时间。

另外,我想您知道命令的输出不能包含0空格包围的空格,除非在正确的位置,但您可以使用例如进行更严格的测试

... | grep -q "^GLOBAL_VARIABLE[[:space:]]*0 " 

GLOBAL_VARIABLE这将检查以零开头的行。

答案2

我会用whilebash 中的循环来测试输出经过的时间:

#!/bin/bash
patience=$((20 * 60))
while ! autorep -g GLOBAL_VARIABLE | grep -q " 0 "  && (( SECONDS < patience ))
do
  sleep $((2 * 60))
done
if (( SECONDS >= patience ))
then
  exit 1
else
  sendevent -E SET_GLOBAL -G "YES"
fi

这个循环直到autorep命令发出该" 0 "行或经过的时间超过耐心变量。这秒变量bash 设置为自 shell 启动以来的秒数;这里,一个新的 shell 正在执行这个脚本,所以它对我们来说就像一个计时器。一旦循环结束,我们就会检查时间是否用完;如果是,exit 1则按要求;否则,执行该sendevent命令。

我明确扩展了耐心变量和睡眠命令的时间戳,以便尽可能清楚地了解所涉及的时间范围。您原来的问题在“睡眠 2”(两秒)和“睡眠 2 分钟”之间存在冲突;上面的代码在测试之间休眠两分钟。

答案3

使用 GNUtimeout命令来记录 20 分钟:

if timeout 20m sh -c '
    until autorep -g GLOBAL_VARIABLE | grep -qF " 0 "; do
        sleep 120
    done'
then
    echo 'did not time out'
else
    echo 'timed out'
fi

timeout如果 20 分钟到期,该命令将以非零退出状态退出。如果设法grep找到它正在寻找的字符串,它将以零退出状态退出。

参数化睡眠时间:

long_sleep=20   # minutes
short_sleep=120 # seconds

if timeout "${long_sleep}m" sh -c '
    short_sleep=$1; shift
    until autorep -g GLOBAL_VARIABLE | grep -qF " 0 "; do
        sleep "$short_sleep"
    done' sh "$short_sleep"
then
    echo 'did not time out'
else
    echo 'timed out'
fi

相关内容