Does a Shell function run in a subshell

lzc picture lzc · Mar 22, 2016 · Viewed 6.9k times · Source

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

My code organization is as follows:

Driver script (in 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:

I tired:

. my_driver.sh

Does not help

If I do it manually from the command line:

source foo.sh

And I set $params manually:

baz $params
bar $params

Then it does work! So it seems that doit or something else acts as if bar and baz are executed from a subshell.

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

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

Answer

rici picture rici · Mar 22, 2016

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

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 |.

db2 requires that the all db2 commands have the same parent as the db2 command which established the connection. You could log the PID using something like:

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

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


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

f()

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