在 Bash 脚本中,如果发生某种情况,如何退出整个脚本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1378274/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 18:29:18  来源:igfitidea点击:

In a Bash script, how can I exit the entire script if a certain condition occurs?

bashscriptingexitexit-code

提问by samoz

I'm writing a script in Bash to test some code. However, it seems silly to run the tests if compiling the code fails in the first place, in which case I'll just abort the tests.

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

Is there a way I can do this without wrapping the entire script inside of a while loop and using breaks? Something like a dun dun dungoto?

有没有一种方法可以在不将整个脚本包装在 while 循环中并使用中断的情况下做到这一点?像dun dun dungoto 之类的东西?

回答by Michael Foukarakis

Try this statement:

试试这个语句:

exit 1

Replace 1with appropriate error codes. See also Exit Codes With Special Meanings.

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

回答by Shizzmo

Use set -e

使用set -e

#!/bin/bash

set -e

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

The script will terminate after the first line that fails (returns nonzero exit code). In this case, command-that-fails2will not run.

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

If you were to check the return status of every single command, your script would look like this:

如果您要检查每个命令的返回状态,您的脚本将如下所示:

#!/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

With set -eit would look like:

使用set -e它看起来像:

#!/bin/bash

set -e

cd /project-dir
make

cd /project-dir2
make

Any command that fails will cause the entire script to fail and return an exit status you can check with $?. If your script is very long or you're building a lot of stuff it's going to get pretty ugly if you add return status checks everywhere.

任何失败的命令都会导致整个脚本失败并返回一个退出状态,你可以用$? . 如果你的脚本很长或者你正在构建很多东西,如果你到处添加返回状态检查,它会变得非常难看。

回答by c.gutierrez

A SysOps guy once taught me the Three-Fingered Claw technique:

一个 SysOps 的人曾经教过我三指爪技术:

yell() { echo "
return <x> 2> /dev/null || exit <x>
: $*" >&2; } die() { yell "$*"; exit 111; } try() { "$@" || die "cannot $*"; }

These functions are *NIX OS and shell flavor-robust. Put them at the beginning of your script (bash or otherwise), try()your statement and code on.

这些函数是 *NIX OS 和 shell 风格的健壮。将它们放在脚本(bash 或其他方式)、try()语句和代码的开头。

Explanation

解释

(based on flying sheepcomment).

(基于 飞羊评论)。

  • yell: print the script name and all arguments to stderr:
    • $0is the path to the script ;
    • $*are all arguments.
    • >&2means >redirect stdout to & pipe 2. pipe 1would be stdoutitself.
  • diedoes the same as yell, but exits with a non-0 exit status, which means “fail”.
  • tryuses the ||(boolean OR), which only evaluates the right side if the left one failed.
  • yell:打印脚本名称和所有参数到stderr
    • $0是脚本的路径;
    • $*都是论据。
    • >&2意味着>将 stdout 重定向到 & pipe2管道1将是stdout它本身。
  • die与 相同yell,但以非 0 退出状态退出,这意味着“失败”。
  • try使用||(boolean OR),如果左侧失败,则仅评估右侧。
    • $@又是所有论点,但不同

回答by kavadias

If you will invoke the script with source, you can use return <x>where <x>will be the script exit status (use a non-zero value for error or false). But if you invoke an executable script (i.e., directly with its filename), the return statement will result in a complain (error message "return: can only `return' from a function or sourced script").

如果您将调用脚本source,您可以使用return <x>其中<x>将脚本退出状态(使用一个非零值的错误或虚假)。但是如果你调用一个可执行脚本(即直接使用它的文件名),return 语句将导致一个错误消息(错误消息“return: can only `return' from a function or sourced script”)。

If exit <x>is used instead, when the script is invoked with source, it will result in exiting the shell that started the script, but an executable script will just terminate, as expected.

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

To handle either case in the same script, you can use

要在同一脚本中处理任一情况,您可以使用

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

This will handle whichever invocation may be suitable. That is assuming you will use this statement at the script's top level. I would advise against directly exiting the script from within a function.

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

Note: <x>is supposed to be just a number.

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

回答by Joseph Sheedy

I often include a function called run() to handle errors. Every call I want to make is passed to this function so the entire script exits when a failure is hit. The advantage of this over the set -e solution is that the script doesn't exit silently when a line fails, and can tell you what the problem is. In the following example, the 3rd line is not executed because the script exits at the call to false.

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

#!/usr/bin/env bash

echo $[1+1]
echo $[2/0]              # division by 0 but execution of script proceeds
echo $[3+1]
(echo $[4/0]) || exit $? # script halted with code 1 returned from `echo`
echo $[5+1]

回答by skalee

Instead of ifconstruct, you can leverage the short-circuit evaluation:

if您可以利用短路评估代替构造:

#!/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

Note the pair of parentheses which is necessary because of priority of alternation operator. $?is a special variable set to exit code of most recently called command.

请注意由于交替运算符的优先级而需要的一对括号。$?是一个特殊变量,设置为最近调用的命令的退出代码。

回答by Gyro Gearloose

I have the same question but cannot ask it because it would be a duplicate.

我有同样的问题,但不能问,因为它会重复。

The accepted answer, using exit, does not work when the script is a bit more complicated. If you use a background process to check for the condition, exit only exits that process, as it runs in a sub-shell. To kill the script, you have to explicitly kill it (at least that is the only way I know).

当脚本有点复杂时,使用 exit 接受的答案不起作用。如果您使用后台进程来检查条件,exit 只会退出该进程,因为它在子 shell 中运行。要杀死脚本,您必须明确地杀死它(至少这是我所知道的唯一方法)。

Here is a little script on how to do it:

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

##代码##

This is a better answer but still incomplete a I really don't know how to get rid of the boompart.

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