在命令不断失败的情况下,shell命令运行“ x”的次数

时间:2019-06-28 06:25:00

标签: bash shell

我正在尝试运行连接到数据库的shell命令(当前为library(tidyverse) df1 %>% separate(names, into = c("first_names", "last_names")) %>% anti_join(df2) %>% unite(unique_names, sep = " ") sh)。由于数据库仍在“预热”,因此命令失败。

所以我试图做一个循环(比方说... 100次尝试),每次命令失败时,请等待1秒钟然后重试。

如果有错误,这是转储到stdout的字符串的开头:bash

这就是我一直在尝试的:

Sqlcmd: Error: <snipped>

当我发现带有shell / bash的字符串比较的东西时,它不起作用...但是要确保我走的路正确等等。

2 个答案:

答案 0 :(得分:2)

您可以尝试以下方法:

while true ; do
    if Sqlcmd xxx xxx xxx ; then break ; fi
    # or:
    Sqlcmd xx xxx xxx && break
    sleep 1
done

您还可以添加一个计数器:

for ((n=100;n>0;n--)) ; do
    Sqlcmd xxx xxx xxx
    if [[ $? == 0 ]] ; then
        break
    fi
    sleep 1
done
[[ $n == 0 ]] && echo Timeout && exit 1

我在这里展示了两种测试返回值的不同方法,但是首选第一种(if cmd ; then ... ; fi)。

$?是最后一条命令的返回值,该命令成功完成时为0。如果即使发生错误(格式错误的程序也可能发生),它仍返回0,则可以使用grep测试输出:

Sqlcmd xxx xxx 2>&1 | grep <error pattern> > /dev/null
if [[ $? != 0 ]] ; then break ; fi

我们在这里测试$? != 0,因为发现错误模式 grep将返回0

如果要将输出结果转换为变量,请使用X=$(Sqlcmd xxx xxx)运行命令。然后您可以使用bash字符串比较:

X=$(Sqlcmd xxx xxx)
if [[ "$X" =~ .*error.* ]] ; then
    <handle error here>
fi

请注意bash可以match regexp,这使得检查错误类型非常方便。

您还可以使用switch/case构造:

case "$X" in
    *Error:*) echo " Error detected " ;;
    *) break ;;
esac

(请注意双;;

答案 1 :(得分:1)

我最终了解了所有线索from @matthieu's post。这就是我最终要做的:

for i in $(seq 1 30)
do
    /opt/mssql-tools/bin/sqlcmd -U sa -P <snip> -S localhost -Q "USE Master" 2>&1

    if [[ $? != 0 ]]
    then
        # Failed
        echo "."
        sleep 1s
    else
        # worked!
        break
    fi
done

像我这样的学习者的细分

  • 使用sqlcmd命令执行sql查询。通过stderr(即2中的2>&1)出现的任何错误都将重定向到控制台stdout(即$1)。参考:2>&1 shell idiom
  • 结果状态代码发送到$?(REF:what is bash dollar questionmark?)
  • 如果失败(任何不为零的值),请休眠1秒钟,我们将尝试。不过,只能重试30次。
  • 如果我们工作了(值是零),请停止尝试并继续。...

所以我们有了它! shell / bash shell 101的东西。祝你好运!