如何安全地提前退出 bash 脚本?

Sto*_*row 6 bash shell exit fail-fast-fail-early

我知道有几个SO问题exitreturnbash脚本(如这里)。

在这个主题上,但与现有问题不同,我相信,我想知道是否有“最佳实践”来安全地从bash脚本中实现“提前返回”,这样用户的当前 shell 就不会退出,如果他们源脚本。

像这样的回答似乎是以“ exit”,但如果脚本来源,即具有运行“ .”(点间隙)前缀,在脚本运行电流外壳的情况下,在这种情况下,exit声明有退出的效果当前外壳。我认为这是一个不受欢迎的结果,因为脚本不知道它是来自还是在子 shell 中运行——如果是前者,用户可能会意外地让他的 shell 消失。如果调用者提供它,是否有提前返回的方法/最佳实践不退出当前 shell?

例如这个脚本...

#! /usr/bin/bash
# f.sh

func()
{
  return 42
}

func
retVal=$?
if [ "${retVal}" -ne 0 ]; then
  exit "${retVal}"
#  return ${retVal} # Can't do this; I get a "./f.sh: line 13: return: can only `return' from a function or sourced script"
fi

echo "don't wanna reach here"
Run Code Online (Sandbox Code Playgroud)

...如果它是从子shell运行的,则不会杀死我当前的shell...

> ./f.sh 
> 
Run Code Online (Sandbox Code Playgroud)

...但如果它是来源,则会杀死我当前的外壳:

> . ./f.sh 
Run Code Online (Sandbox Code Playgroud)

想到的一个想法是将代码嵌套在条件中,这样就没有明确的exit声明,但我的C/C++偏见使早期返回在美学上比嵌套代码更可取。还有其他真正“早退”的解决方案吗?

alv*_*its 9

在不导致父 shell 终止的情况下退出脚本的最常见解决方案是先尝试return。如果它失败了exit

您的代码将如下所示:

#! /usr/bin/bash
# f.sh

func()
{
  return 42
}

func
retVal=$?
if [ "${retVal}" -ne 0 ]; then
  return ${retVal} 2>/dev/null # this will attempt to return
  exit "${retVal}" # this will get executed if the above failed.
fi

echo "don't wanna reach here"
Run Code Online (Sandbox Code Playgroud)

您也可以使用return ${retVal} 2>/dev/null || exit "${retVal}".

希望这可以帮助。