Shell函数是否在子shell

时间:2016-03-22 15:33:51

标签: bash subshell

我试图解决一个问题,在我看来,你无法将开放的db2连接传递给子shell。

我的代码组织如下:

驱动程序脚本(在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

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

my_driver.sh

现在,我真正的问题是子shell中没有db2连接:

我累了:

. my_driver.sh

没有帮助

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

source foo.sh

我手动设置$params

baz $params
bar $params

然后它确实有效!因此,似乎doit或其他内容的行为就像从子shell执行barbaz一样。

如果我能以某种方式弄清楚如何将db2 open connection传递给subshel​​l,那我会很高兴。

否则,这些shell函数在我看来是在子shell中运行的。有办法吗?

2 个答案:

答案 0 :(得分:6)

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

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

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

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

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

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

function f

定义一个功能。期望标准shell

f()

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

答案 1 :(得分:0)

找到解决方案,但无法完全解释问题....

如果你按照以下方式更改function doit { while read params do baz $params bar $params done < $param_file } 就行了!

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

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

如果我坚持使用调试代码:

|

我与cat $param_file | while read params取得了相同的结果。我知道while (false != $row = mysqli_fetch_assoc($query2)) echo $row["total_likes"]; 创建了一个子shell,但是,我的调试语句总是显示相同的PID和PPID ......

所以我的问题解决了,但我错过了一些解释。

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