我正在Bash中编写一个脚本来测试一些代码。但是,如果编译代码一开始就失败了,那么运行测试似乎很愚蠢,在这种情况下,我将中止测试。

有没有一种方法,我可以这样做,而不包装整个脚本在一个while循环和使用中断?像是叮叮当当的后藤?


当前回答

我有同样的问题,但不能问,因为这将是一个重复。

当脚本稍微复杂一些时,使用exit的公认答案将不起作用。如果使用后台进程检查条件,exit只退出该进程,因为它在子shell中运行。要终止脚本,必须显式地终止它(至少这是我所知道的唯一方法)。

这里有一个关于如何做到这一点的小脚本:

#!/bin/bash

boom() {
    while true; do sleep 1.2; echo boom; done
}

f() {
    echo Hello
    N=0
    while
        ((N++ <10))
    do
        sleep 1
        echo $N
        #        ((N > 5)) && exit 4 # does not work
        ((N > 5)) && { kill -9 $$; exit 5; } # works 
    done
}

boom &
f &

while true; do sleep 0.5; echo beep; done

这是一个更好的答案,但仍然不完整,我真的不知道如何摆脱boom部分。

其他回答

试试这句话:

exit 1

用适当的错误代码替换1。请参见具有特殊含义的退出代码。

如果您将使用source调用脚本,您可以使用return <x>,其中<x>将是脚本退出状态(使用非零值表示错误或false)。但是如果你调用一个可执行脚本(即直接使用它的文件名),return语句将导致一个抱怨(错误消息“return:只能从函数或源脚本中' return'”)。

如果使用exit <x>代替,当使用source调用脚本时,它将导致退出启动脚本的shell,但可执行脚本将如预期的那样终止。

要在同一个脚本中处理这两种情况,可以使用

return <x> 2> /dev/null || exit <x>

这将处理任何合适的调用。这是假设您将在脚本的顶层使用此语句。我建议不要直接从函数中退出脚本。

注意:<x>应该只是一个数字。

我经常包含一个名为run()的函数来处理错误。我想进行的每个调用都传递给这个函数,因此当遇到失败时整个脚本都会退出。与set -e解决方案相比,这种方法的优点是,当一行失败时,脚本不会静默退出,并且可以告诉您问题是什么。在下面的示例中,第三行没有执行,因为脚本在调用false时退出。

function run() {
  cmd_output=$(eval $1)
  return_value=$?
  if [ $return_value != 0 ]; then
    echo "Command $1 failed"
    exit -1
  else
    echo "output: $cmd_output"
    echo "Command succeeded."
  fi
  return $return_value
}
run "date"
run "false"
run "date"

使用set -e

#!/bin/bash

set -e

/bin/command-that-fails
/bin/command-that-fails2

脚本将在第一行失败后终止(返回非零退出代码)。在这种情况下,command-that-fails2将不会运行。

如果你要检查每一个命令的返回状态,你的脚本看起来像这样:

#!/bin/bash

# I'm assuming you're using make

cd /project-dir
make
if [[ $? -ne 0 ]] ; then
    exit 1
fi

cd /project-dir2
make
if [[ $? -ne 0 ]] ; then
    exit 1
fi

使用set -e,它看起来像:

#!/bin/bash

set -e

cd /project-dir
make

cd /project-dir2
make

任何失败的命令都将导致整个脚本失败,并返回一个退出状态,您可以使用$?如果你的脚本很长,或者你构建了很多东西,如果你到处添加返回状态检查,那就会很难看。

您可以通过以下方式通过程序名称关闭程序:

对于软退出做

pkill -9 -x programname # Replace "programmname" by your programme

对于硬出口

pkill -15 -x programname # Replace "programmname" by your programme

如果你想知道如何评估关闭程序的条件,你需要定制你的问题。