Bash shell variables lost when using a script from inside a function

I ran into some strange (for me) problem in Cygwin bash version 4.3.42 (4). Shell variables declared in the called script are not saved in the calling script when the first is called from the function.

I have two scenarios to illustrate the problem. script1.sh calls script2.sh, which sets two variables. If script2 is called using a function in script1, the variables are lost, and if script2 is called without calling the function, the variables are saved as expected. All calls to script2 are made through the "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=$$" 

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 do not see any subnets that are created (the same PID is shown everywhere).

Am I missing a thinner point in a bash script?

+5
source share
2 answers

I have two scenarios to illustrate the problem. script1.sh calls script2.sh, which sets two variables. If script2 is called through a function in script1, the variables are lost,

No, your result shows that the value of the rval variable is lost after returning from the function, but the value of the sval variable is saved.

whereas if script2 is called without calling the function, the variables are saved as expected. All calls to script2 are made through the "source".

Since there is a difference between the behavior of rval and sval , you should look at script2.sh for the difference in how they are processed, et voilà! it turns out that rval assigned its value through the built-in declare , while sval assigned its value directly. After looking at the documentation for declare , we will find:

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

Local variables in bash similar to local variables in most other languages ​​- they are different from other variables that have the same name, and within their scope they are shadow variables with a name, called names, from the contained areas. Thus, your code sets and parses the same sval variable everywhere, in each case, but sets and parses a different rval inside the function than anywhere else.

+3
source

I began to answer this question, but I was interrupted by putting together the information and just returned to it now. I see that John Bollinger has more than adequately answered questions about functions and the scope of variables, so I can not leave this part of my answer.

Headrests and $$

I do not see any subnets that are created (the same PID is shown everywhere).

If the commands were executed in a subshell, they will work in the child process with a different PID than the original shell.

However, it is 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 experimented with subshells.

However, Bash sets the special variable BASHPID to the actual PID of the shell process (which makes changes to subshells). These sequences of commands demonstrate this.

Show the PID of the current shell:

 $ echo $$ 1469 $ echo $BASHPID 1469 

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

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

Relevant Links

+3
source

Source: https://habr.com/ru/post/1238984/


All Articles