如何安全地退出bash脚本?

时间:2018-08-24 22:30:11

标签: bash shell exit fail-fast-fail-early

我知道exit脚本(例如here)中的returnbash有几个SO问题。

在这个主题上,我相信,与现有问题不同,我想知道是否存在一种“最佳实践”,说明如何从bash脚本中安全地实现“早期返回”,从而如果用户提供脚本,则不会退出用户的当前shell。

诸如this之类的答案似乎基于“ exit”,但是如果脚本是源文件,即以“ .”(点号)前缀运行,则该脚本以当前外壳的上下文,在这种情况下,exit语句具有退出当前外壳的作用。我认为这是不希望的结果,因为脚本不知道它是源程序还是在子外壳程序中运行-如果是前者,则用户可能会意外地删除其外壳程序。有没有一种方法/最佳实践,可以在调用者提供源的情况下尽早返回而不退出当前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"

...运行时不会杀死我当前的外壳(如果它是从子外壳运行的...

> ./f.sh 
> 

...但是杀死了我当前的外壳(如果它是源外壳):

> . ./f.sh 

想到的一个想法是将代码嵌套在条件代码中,这样就没有显式的exit语句,但是我的C / C++偏见使早期返回在美学上显得很美优于嵌套代码。还有其他真正“尽早返回”的解决方案吗?

1 个答案:

答案 0 :(得分:2)

在不导致父外壳终止的情况下退出脚本的最常见解决方案是首先尝试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"

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

希望这会有所帮助。