【问题标题】:Does a Shell function run in a subshellShell函数是否在子shell中运行
【发布时间】:2016-03-28 06:07:07
【问题描述】:

我正在尝试解决一个问题,在我看来,您无法将打开的 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

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

我累了:

. my_driver.sh

没用

如果我从命令行手动执行:

source foo.sh

我手动设置$params

baz $params
bar $params

然后它确实有效!所以看起来doit 或其他东西的行为就像barbaz 是从一个子shell 执行的。

如果我能以某种方式弄清楚如何将 db2 开放连接传递给 subshel​​l,我会很高兴。

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

【问题讨论】:

  • 我认为答案对你来说是显而易见的。是的,它在一个子shell中!您可以通过尝试打印环境变量来轻松测试。
  • 是的,它是.. 但是可以我在子shell中运行barbaz
  • 在您的代码中,我看不到bazbar 在子shell 中运行的任何可能性。可能他们自己在子 shell 中运行 db2 命令?
  • 感谢@dekkard 你让我思考 :) 所以现在,我仍然不确定barbaz 是否确实在子shell 中被调用,但是我通过在{ curlies } 中环绕我的db2 调用解决了我的问题!
  • 最后一条评论只是错误,嗯,我怎么能只删除评论呢?

标签: bash subshell


【解决方案1】:

shell 不会创建子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。

【讨论】:

  • 仅供参考:我使用的是 bash,而使用 function 关键字的 AFAIK 是 optional 也是 >> /dev/stderr 具有误导性,或者出于某种原因它对我不起作用...你意思是说:echo hello world 2>> /tmp/my_stderr.log >&2?
【解决方案2】:

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

如果您按以下方式更改doit,它会起作用!

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 创建了一个子shell,但是,我的调试语句总是显示相同的PID 和PPID...

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

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

【讨论】:

  • 调试代码中的BASH_SUBSHELL变量确实表明|右侧是一个子shell ...因此任何后续的 db2 调用都不再在父 shell 中!
猜你喜欢
  • 2014-05-26
  • 2013-03-05
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
  • 2015-08-03
  • 2014-06-26
  • 2022-12-21
  • 2013-12-08
相关资源
最近更新 更多