bash Shell 函数是否在子shell 中运行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36158686/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 14:23:59  来源:igfitidea点击:

Does a Shell function run in a subshell

bashsubshell

提问by lzc

I'm trying to get around a problem seems to me that you cannot pass open db2 connection to a subshell.

我正在尝试解决一个问题,在我看来,您无法将打开的 db2 连接传递给子 shell。

My code organization is as follows:

我的代码组织如下:

Driver script(in my_driver.sh)

驱动程序脚本(中my_driver.sh

# foo.sh defines baz() bar(), which use a db2 connection
# Also the "$param_file" is set in foo.sh!
source foo.sh

db2 "connect to $dbName USER $dbUser using $dbPass"

function doit
{
    cat $param_file | while read params
    do
        baz $params
        bar $params
    done
}

doit

I've simplified my code, but the above is enough the give the idea. I start the above:

我已经简化了我的代码,但上面的内容已经足够了。我从上面开始:

my_driver.sh

Now, my real issue is that the db2 connection is not available in subshell:

现在,我真正的问题是 db2 连接在 subshel​​l 中不可用:

I tired:

我累了:

. my_driver.sh

Does not help

没有帮助

If I do it manually from the command line:

如果我从命令行手动执行此操作:

source foo.sh

And I set $paramsmanually:

$params手动设置:

baz $params
bar $params

Then it does work! So it seems that doitor something else acts as if barand bazare executed from a subshell.

然后它起作用了!如此看来,doit还是别的什么行为,如果barbaz从子shell执行。

I would be elated if I can somehow figure out how to pass db2 open connection to subshell would be best.

如果我能以某种方式弄清楚如何将 db2 打开连接传递到 subshel​​l 是最好的,我会很高兴。

Otherwise, these shell functions seems to me that they run in a subshell. Is there a way around that?

否则,在我看来,这些 shell 函数在子 shell 中运行。有没有办法解决这个问题?

回答by rici

The shell does not create a subshell to run a function.

shell 不会创建子 shell 来运行函数。

Of course, it does create subshells for many other purposes, not all of which might be obvious. For example, it creates subshells in the implementation of |.

当然,它确实为许多其他目的创建了子 shell,并非所有这些目的都是显而易见的。例如,它在|.

db2requires that the all db2commands have the same parent as the db2command which established the connection. You could log the PID using something like:

db2要求所有db2命令与db2建立连接的命令具有相同的父级。您可以使用以下方式记录 PID:

echo "Execute db2 from PID $$" >> /dev/stderr
db2 ...

(as long as the db2 command isn't execute inside a pipe or shell parentheses.)

(只要 db2 命令不在管道或 shell 括号内执行。)



One possible problem in the code shown (which would have quite a different symptom) is the use of the non-standard syntax

所示代码中的一个可能问题(会有完全不同的症状)是使用了非标准语法

function f

To define a function. A standard shell expects

定义一个函数。一个标准的 shell 期望

f()

Bash understands both, but if you don't have a shebang line or you execute the scriptfile using the shcommand, you will end up using the system's default shell, which might not be bash.

Bash 理解两者,但如果您没有 shebang 行或使用sh命令执行脚本文件,您最终将使用系统的默认 shell,它可能不是 bash。

回答by lzc

Found solution, but can't yet fullyexplain the problem ....

找到解决方案,但还不能完全解释问题....

if you change doitas follows it works!

如果您doit按如下方式更改它就可以了!

function doit
{
    while read params
    do
        baz $params
        bar $params
    done < $param_file
}

Only, I'm not sure why? and how I can prove it ...

只是,我不知道为什么?以及我如何证明它...

If I stick in debug code:

如果我坚持调试代码:

echo debug check with PID=$$ PPID=$PPID and SHLVL=$SHLVL

I get back same results with the |or not. I do understand that cat $param_file | while read paramscreates a subshell, however, my debug statements always show the same PID and PPID...

我得到与|或不相同的结果。我知道cat $param_file | while read params创建一个子shell,但是,我的调试语句总是显示相同的 PID 和 PPID ...

So my problem is solved, but I'm missing some explanations.

所以我的问题解决了,但我缺少一些解释。

I also wonder if this question would not be more well suited in the unix.stackexchange community?

我也想知道这个问题是否更适合 unix.stackexchange 社区?