【问题标题】:exit function stack without exiting shell退出函数堆栈而不退出 shell
【发布时间】:2012-06-23 20:42:00
【问题描述】:

我正在编写一个脚本,然后遇到了一个奇怪的问题。如果我要获取一个包含一堆函数的脚本,这些函数可能会调用一个输出字符串然后退出的错误函数,它将退出我的 shell。我知道它为什么这样做。这是因为函数调用与调用者在同一个进程空间中(至少它在 bash 中),所以函数内的退出使用提供的退出代码终止当前进程。示例:

error()
{
  echo $1
  exit 1
}

fn()
{
  if [ $# == 0 ]; then
    error "Insufficient parameters."
  fi
  # do stuff
}

$ fn
Insufficient parameters.
[shell terminates]

所以我的问题是,我可以退出函数堆栈中的所有函数而不终止当前 shell 并且不产生新的子 shell 吗?

谢谢

【问题讨论】:

    标签: bash function shell exit


    【解决方案1】:

    要在不退出shell的情况下退出函数堆栈,可以使用以下命令:

    kill -INT $$
    

    正如pizza 所说,这就像按 Ctrl-C,它将停止当前脚本的运行并将您带到命令提示符。

     

     


    注意:我没有选择pizza的答案的唯一原因是因为这被埋在他/她的答案中,没有直接回答。

    【讨论】:

    • 下面的“return”似乎更可取:这是为此目的内置到外壳中的功能。杀死 shell 是不优雅的。
    • @JPGConnolly The following "return" is preferable it seems 是什么意思?如果您的意思是使用内置的return 语句,那么您没有阅读该问题,因为没有简单的方法可以使用它,这样它就会从一个称为多个函数的函数中跳回基本 shell,而不必询问每个函数调用的返回值,这在某些情况下是不切实际或不可能的。在这种情况下,使用kill -INT $$ 比使用return 要优雅得多。
    • $ 的值是多少?源函数的调用者看到了吗?还是它也终止了?
    • @Michael,$$的值是shell进程的pid。
    • @JPGConnolly ...据我了解,我们希望在不退出 shell 的情况下从 source-d 脚本中中断。这绝对是我来这里的原因。它用于中止的“escape”源代码。请原谅我指出该功能在 Windows(批处理)shell 中可用 exit /b - 仅退出脚本,而不是 shell(窗口)。
    【解决方案2】:

    你可以做一个

    exit() { return $1;}
    

    然后

    source ./your_script 
    

    回答怀疑者,这只会影响当前的 shell,不会影响你生成的 shell。

    信息量更大的形式可以是

    exit() {
        local ans
        local line
        read -p "You really want to exit this? " line
        ans=$(echo $line)
        case "$ans" in
                Y);;
                y);;
                *)kill -INT $$;;
        esac
        unset -f exit
        exit $1
    }
    

    【讨论】:

    • 这不是有效的 Bash 语法。
    • 这行不通。它只会导致返回错误的函数。不是我想要的。
    • 如果您不希望它返回,您可以将“return $1”替换为“kill -INT $$”,这会在提示符中将其带回您当前的 shell。
    • 就像按 control-C 一样,它不会杀死当前的 shell,它会展开所有当前函数并返回到提示符。
    • 这是一个有用的技巧,可以避免在不触及现有代码的情况下退出。但是,如果代码要在用户当前的 shell 上下文中运行并且可以修改,我推荐kill -INT $$;
    【解决方案3】:

    您需要在每个函数中添加return 语句,以检查它们依次调用的任何函数的返回值。获取文件就像将代码剪切并粘贴到当前上下文中一样,除了 $BASH_SOURCE 等变量的小例外。

    或者,您可以将 fn 定义为 shell 脚本,以便 exit 执行您想要的操作(除非分叉太贵)。

    【讨论】:

    • 检查所有函数退出值是没有用的。目前,为了解决这个问题,我让 shell 脚本调用其中的各个函数。因此退出它不会退出我的shell。
    • 您不需要检查所有退出值 - 只需检查它是否成功 - if my_function - 或者退出代码是否非零 - my_function; if [ $? -ne 0 ]
    • 将函数定义为 shell 脚本是一个很好的解决方案,但是在该函数中使用“exit”将退出 shell。您使用“return”在不退出 shell 的情况下停止功能是正确的。
    【解决方案4】:

    shell 并没有真正的异常机制来一次回退许多函数调用。您只需检查返回值并手动返回。

    【讨论】:

    • 我正在检查。只想退出当前正在运行的所有函数而不退出shell。
    • 这意味着您使用return 而不是exit。但我的意思是,你必须在每个函数内部都做一个单独的return,而不仅仅是在最里面一次。
    • 不幸的是,这对我想做的事情没有用。
    【解决方案5】:

    使用return语句,但调用错误后需要添加return

    【讨论】:

    • 函数返回不需要返回语句。
    • 但 OP 希望函数立即终止,而不是在它到达函数体底部时终止。
    • 我希望堆栈上的所有函数都终止。 "but in the if ; before do stuff" 是什么意思?
    • 我在回答 Dennis,Adrian,为什么不在新函数中生成新 shell,这是我认为最简单的解决方案:fnc() (fn),或者更容易阅读 fnc() { ( fn)}
    • @Wildcard 如果调用是函数的最后一条语句,则隐式返回状态,否则为特殊变量 $?可以用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-28
    相关资源
    最近更新 更多