如何打破源Bash脚本的功能

d3p*_*3pd 5 bash return exit terminate

我有一个源代码的Bash脚本.当这个脚本来源时,它在Bash脚本中运行一个函数.如果匹配某个条件,此函数应终止脚本.如何在不终止脚本所在的shell的情况下完成此操作?

要明确:我希望终止操作由源shell脚本中的函数完成,而不是在源shell脚本的主体中完成.我可以看到的问题是,returnexit 1终止调用shell时,只需从函数返回到脚本的main .

以下最小示例说明了此问题:

main(){
    echo "starting test of environment..."
    ensure_environment
    echo "environment safe -- starting other procedures..."
}

ensure_environment(){
    if [ 1 == 1 ]; then
        echo "environment problemm -- terminating..."
        # exit 1 # <-- terminates calling shell
        return   # <-- returns only from function, not from sourced script
    fi
}

main
Run Code Online (Sandbox Code Playgroud)

Eta*_*ner 8

您可以return从源shell脚本中获取.POSIX规范

所以,虽然你不能return直接从函数中得到你想要的东西,但如果你的函数返回非零(或其他一些约定的值),你可以从脚本的主体返回.

例如:

$ cat foo.sh
f() {
    echo in f "$@"
}

e() {
    return 2
}

f 1
e
f 2
if ! e; then
    return
fi
f 3
$ . foo.sh
in f 1
in f 2
Run Code Online (Sandbox Code Playgroud)


Lud*_*lze 3

这是一个如何通过你的方法实现你的目标的秘诀。我不会为您编写代码,只是描述如何完成它。

您的目标是通过有效地获取可能复杂的 shell 脚本来设置/更改当前 bash shell 中的环境变量。该脚本的某些组件可能会决定应停止执行该源脚本。使事情变得复杂的是,这个决定不一定是顶层的,但可能位于嵌套函数调用中。return,那么,没有帮助,并且exit会终止采购 shell,这是不希望的。

您的以下声明使您的任务变得更加容易:

我无法在一个最小的示例中真正包含额外的复杂性,因此非常需要将终止过程集中在函数中。

您可以这样做:

您不是采购真正的脚本来决定将哪个环境设置为什么(“ realscript.bash”),而是采购另一个脚本“ ipcscript.bash”。

ipcscript.bash将设置一些进程间通信。这可能是您使用 exec 打开的某个额外文件描述符上的管道,它可能是临时文件,也可能是其他文件。

ipcscript.bash然后将realscript.bash作为子进程启动。这意味着,首先发生的环境更改realscript.bash只会影响 bash 子进程实例的环境。作为子进程启动realscript.bash,您可以获得在任何嵌套级别通过 exit 终止执行的能力,而无需终止源 shell。

正如您所写,您对 exit 的调用将存在于一个集中函数中,当决定终止执行时,该函数会从任何级别调用。您的终止函数现在需要在退出之前以合适的格式将当前环境写入 IPC 机制。

ipcscript.bash将从IPC机制中读取环境设置并在采购shell过程中重现所有设置。