![脚本在 Y 分钟内每 X 分钟重复一次“if”语句,如果不成立则失败](https://linux22.com/image/194049/%E8%84%9A%E6%9C%AC%E5%9C%A8%20Y%20%E5%88%86%E9%92%9F%E5%86%85%E6%AF%8F%20X%20%E5%88%86%E9%92%9F%E9%87%8D%E5%A4%8D%E4%B8%80%E6%AC%A1%E2%80%9Cif%E2%80%9D%E8%AF%AD%E5%8F%A5%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E6%88%90%E7%AB%8B%E5%88%99%E5%A4%B1%E8%B4%A5.png)
“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
我会用while
bash 中的循环来测试输出和经过的时间:
#!/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