I've encountered a strange (to me) problem in Cygwin bash version 4.3.42(4). Shell variables that are declared in a called script do not persist in the calling script when the former is called from within a function.
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, whereas if script2 is invoked without the function call, the variables persist as expected. All invocations of script2 are done via "source".
script1.sh:
#!/usr/bin/bash
#
# calling script
#
function sourceit()
{
source scripts/script2.sh
}
sval=1
echo "$0 before sourceit(); rval=$rval sval=$sval PID=$$"
sourceit
echo "$0 after sourceit(); rval=$rval sval=$sval PID=$$"
sval=3
echo "$0 before source; rval=$rval sval=$sval PID=$$"
source scripts/script2.sh
echo "$0 after source; rval=$rval sval=$sval PID=$$"
script2.sh
#!/usr/bin/bash
#
# called script
#
echo "$0 before declare; rval=$rval sval=$sval PID=$$"
sval=2
declare -r rval=2
echo "$0 after declare; rval=$rval sval=$sval PID=$$"
The results:
scripts/script1.sh before sourceit(); rval= sval=1 PID=1752
scripts/script1.sh before declare; rval= sval=1 PID=1752
scripts/script1.sh after declare; rval=2 sval=2 PID=1752
scripts/script1.sh after sourceit(); rval= sval=2 PID=1752
scripts/script1.sh before source; rval= sval=3 PID=1752
scripts/script1.sh before declare; rval= sval=3 PID=1752
scripts/script1.sh after declare; rval=2 sval=2 PID=1752
scripts/script1.sh after source; rval=2 sval=2 PID=1752
I don't see any subshells being created (the same PID is shown everywhere).
Am I missing a finer point of bash scripting?
I had started answering this question but I was interrupted while putting together 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.
$$
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 child process with a different PID than the parent shell.
However, it’s worth noting that with Bash, subshells actually inherit the
value 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 $BASHPID
1469
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
This article on Compound commands is relevant to your question as it explains both subshells and shell functions.
Sourcing shell commands
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With