Bash shell variables lost when script sourced from within a function Bash shell variables lost when script sourced from within a function shell shell

Bash shell variables lost when script sourced from within a function


I had started answering this question but I was interrupted while puttingtogether the information and have only just came back to it now. I see that John Bollinger has already more than adequately answered the questions about functions and variable scope so I’ll leave out that part of my answer.

Subshells and $$

I don't see any subshells being created (the same PID is shown everywhere).

If commands were to run in a subshell, they would be running in a childprocess with a different PID than the parent shell.

However, it’s worth noting that with Bash, subshells actually inherit thevalue of the $$ special variable from the parent shell. This caused me some confusion when I was experimenting with subshells.

However, Bash sets the BASHPID special variable to the actual PID of the shell process (which does change in subshells). The following command sequences demonstrate this.

Show the PID of the current shell:

$ echo $$1469$ echo $BASHPID1469

Within the parentheses, these two commands are run in a subshell. Only the Bash-specific BASHPID special variable shows the actual PID of the subshell process.

$ (echo $$)1469$ (echo $BASHPID)8806

Relevant links


I have the following two scripts to illustrate the issue. script1.sh calls script2.sh which sets two variables. If script2 is invoked via a function in script1, the variables are lost,

Well no, your output shows that the value of variable rval is lost after return from the function, but the value of variable sval is retained.

whereas if script2 is invoked without the function call, the variables persist as expected. All invocations of script2 are done via "source".

Since there is a distinction between the behavior of rval and sval, you should look in script2.sh for a difference in how they are handled, et voilà! it turns out that rval is assigned its value via the declare built-in, whereas sval is assigned its value directly. Looking at the documentation for declare, then, we find:

When used in a function, makes each name local, as with the local command.

Local variables in bash are just like local variables in most other languages -- they are distinct from other variables having the same name, and within their scope they shadow like-named variables from containing scopes. Thus, your code sets and examines the same variable sval everywhere, in each case, but it sets and examines a different rval inside the function than it does anywhere else.