【问题标题】:Return an exit code without closing shell在不关闭 shell 的情况下返回退出代码
【发布时间】:2011-09-01 00:52:42
【问题描述】:

我想从 BASH 脚本返回一个退出代码,该代码在另一个脚本中调用,但也可以直接调用。大致是这样的:

#!/bin/bash
dq2-get $1
if [ $? -ne 0 ]; then
  echo "ERROR: ..."
  # EXIT HERE
fi
# extract, do some stuff
# ...

现在在 EXIT HERE 行中,脚本应该退出并返回退出代码 1。问题在于

  • 我不能使用return,因为当我忘记获取脚本而不是调用它时,返回将不会退出,并且脚本的其余部分将被执行并搞砸了。
  • 我不能使用exit,因为这会关闭外壳。
  • 我不能使用漂亮的技巧kill -SIGINT $$,因为这不允许返回退出代码。

有没有我忽略的可行替代方案?

【问题讨论】:

  • 我的建议是不要忘记获取脚本。
  • 软件的编写方式应始终确保误用不会导致问题。
  • 我不同意尼尔斯的建议。相反,永远不要获取脚本,而是始终调用它。
  • 检查$SHLVL的值是否有条件退出。

标签: bash return exit return-code


【解决方案1】:

问题标题的答案(不像其他答案那样在正文中)是:

在不关闭 shell 的情况下返回退出代码

(exit 33)

如果您需要激活 -e 并且仍然避免使用非零退出代码退出 shell,请执行以下操作:

(exit 33) && true

true 命令从不执行,但用于构建不会被-e shell 标志退出的复合命令。

设置退出代码而不退出 shell(也不是源脚本)。

对于更复杂的退出问题(带有特定退出代码),无论是执行还是获取:

#!/bin/bash
[ "$BASH_SOURCE" == "$0" ] &&
    echo "This file is meant to be sourced, not executed" && 
        exit 30

return 88

如果执行,将设置退出代码 30(带有错误消息)。
如果有来源,退出代码为 88。 将退出 both 执行或采购,而不影响调用 shell。

【讨论】:

  • (exit 33) 太棒了!!
  • 这非常有用。不过,我遇到的一件事是我喜欢使用“set -e”来停止脚本的运行。不幸的是 return 88 会导致它像以前一样杀死shell。有没有关于能够处理这种情况的指示?
  • @openCivilisation 即使设置了-e 选项,保持shell 工作的通常解决方案是使命令行成为复合命令,最简单的复合命令是(exit 33) && true。真正的命令从未真正执行过。
【解决方案2】:

用这个代替退出或返回:

[ $PS1 ] && return || exit;

无论是否采购都有效。

【讨论】:

  • 如果使用单括号[ ] 而不是双括号[[ ]],它也适用于sh
  • 它对我写的不起作用(作为脚本运行不起作用),但以下工作:[ -v PS1 ] && return || exit。一种轻松测试的方法:[ -v PS1 ] && (echo returning; return) || (echo exiting; exit)
  • 另外,如果我理解正确,这个解决方案在从另一个脚本中获取源时不起作用。不过,接受的答案适用于那个(复杂的)场景。
【解决方案3】:

您可以使用x"${BASH_SOURCE[0]}" == x"$0" 来测试脚本是否被源或调用(如果源是false,如果调用是true)和returnexit 相应地。

【讨论】:

  • 我试过了,但我很无聊,因为我不能把它放到 function 中(因为我又会错过退出的方式)——我必须把在脚本中可能发生错误的每个地方都有一个if 构造。还是有更好的办法?
  • 你可以让 if 语句成为信号陷阱的一部分,然后用 kill -SIGWHATEVER $$ 替换每个 EXIT HERE
【解决方案4】:

另一种选择是使用函数并将返回值放入其中,然后简单地获取脚本 (source processStatus.sh) 或调用脚本 (./processStatus.sh)。例如,考虑 processStatus.sh 脚本,它需要向 stopProcess.sh 脚本返回一个值,但也需要在不使用源的情况下与命令行分开调用(仅包括相关部分) 例如:

check_process ()
{
  if [ $1 -eq "50" ]
  then
    return 1       
  else
    return 0
  fi       
}

source processStatus.sh $1
RET_VALUE=$?
if [ $RET_VALUE -ne "0" ]
then
  exit 0
fi

【讨论】:

    【解决方案5】:

    如果你use set -e in the beginning of the script.,你可以使用return

    如果你只是想检查函数是否没有返回错误,我宁愿建议像这样重写你的代码:

    #!/bin/bash
    
    set -e # exit program if encountered errors
    
    dq2-get ()
    {
      # define the function here
      # ...
      if [ $1 -eq 0 ]
      then
        return 0
      else
        return 255
      # Note that nothing will execute from this point on,
      # because `return` terminates the function.
    }
    
    # ...
    # lots of code ...
    # ...
    
    # Now, the test:
    # This won't exit the program.
    if $(dq2-get $1); then
      echo "No errors, everything's fine"
    else
      echo "ERROR: ..."
    fi
    # These commands execute anyway, no matter what
    # `dq2-get $1` returns (i.e. {0..255}).
    # extract, do some stuff
    # ...
    

    现在,如果函数dq2-get $1 返回错误,上面的代码将不会离开程序。但是,由于set -e,单独实现该功能将退出程序。下面的代码描述了这种情况:

    # The function below will stop the program and exit
    # if it returns anything other than `0`
    # since `set -e` means stop if encountered any errors.
    $(dq2-get $1)
    # These commands execute ONLY if `dq2-get $1` returns `0`
    # extract, do some stuff
    # ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多