我正在运行一个可能会遇到错误的命令:
cmd sub-cmd --param1 value1 --param2 value2
该命令有可能返回错误。错误消息是一个特定的错误消息,以某个字符串结尾(开头不同,但结尾始终相同)。我正在寻找一个小的 shell 脚本代码来重试相同的命令,以防cmd
返回以特定字符串结尾的错误消息一定次数(比方说 5 次)。另外,请注意cmd
接受参数,我希望 shell 脚本能够将它得到的任何内容传递给我的cmd
.如果错误消息不是我要查找的错误消息,则 shell 脚本应返回错误并停止 ( exit(1)
)。谢谢。
答案1
然后我们需要捕获命令的输出。如果我们可以捕获所有内容(或者只是忽略标准输出),这是最简单的:
#!/bin/bash
errormsg=$( cmd "$@" 2>&1 >/dev/null )
re="known error message$"
if [[ $errormsg =~ $re ]]; then
echo "cmd failed with known message
fi
命令替换$(..)
和其中的重定向捕获命令的标准错误输出,并将非错误输出重定向到/dev/null
.然后我们将其与正则表达式进行比较,其中$
末尾的 表示字符串的结尾。 (命令替换会删除所有尾随换行符,因此正则表达式不需要匹配这些换行符。)"$@"
扩展到脚本的参数,将它们作为参数传递给cmd
.
当然,我们需要一个循环来重复运行程序。命令替换的替代方法是使用临时文件来存储错误输出并随后查看它。这也使得命令的标准输出可见变得更加容易,所以让我们这样做:
#!/bin/bash
re="known error message$"
retries=0
max_retries=5
errorfile=$(mktemp) # temp file for the errors
trap 'rm "$errorfile"' EXIT # remove the temp file on exit
while cmd "$@" 2> "$errorfile"; # run the command
ret=$?; # save the exit code
[[ $( < $errorfile ) =~ $re ]]; do # check the output
cat "$errorfile" >&2 # print the errors to
# the script's stderr, too
retries=$((retries+1)) # retry a couple of times
echo -n "cmd failed with known message"
if [[ $retries -lt $max_retries ]]; then
echo ", retrying."
else
echo ", exit."
exit 1
fi
done
cat "$errorfile" >&2
echo "cmd completed with status $ret"; # use saved exit code, since it might
exit "$ret" # have failed for other reasons
(while cmd1; cmd2; do ...
运行指令1一开始,然后运行指令2作为循环条件。)
在上面,我忽略了命令的实际退出状态,只查看输出。如果您想考虑退出状态,则需要更改脚本。