In my current project, I run a loop that during execution defines a variable that is required later on.
Everything worked well until I wanted to add logging with tee, so that I
later could inspect the log also in a file.
As I wanted to log both, stdout and stderr, I applied |&
(the shortcut of 2>&1 |
).
But strangely, the variable's value gets lost then.
for i in 1 2 3 ; do
# ... do something meaningful ...
myVar=test1
done |& tee test1
echo "myVar=$myVar"
Output:
myVar=
Meanwhile I found a way, that works better: When I switch to a combination of file redirection and process substitution, the variable definition works.
for i in 1 2 3 ; do
# ... do something meaningful ...
myVar=test2
done > >(tee test2 ) \
2> >(tee test2 >&2)
echo "myVar=$myVar"
Output:
myVar=foo
But I want to understand, why :-)
Can you tell?
As 123 said a pipe creates a sub shell (a new scope) and a sub shell has no access to the variables of the parent shell.
The following helper function shows the PID of the shell and the value of the variable a
.
show_a () { echo $BASHPID: a=$a >&2; }
The following example creates no sub shell, because only redirection is used. Only one variable a
is used.
$ a=1; show_a; { a=2; show_a; } > /dev/null ; show_a
31072: a=1
31072: a=2
31072: a=2
But this example creates a sub shell, because of the pipe. And each process has its own variable a
.
$ a=1; show_a; { a=2; show_a; } | tee ; show_a
31072: a=1
6375: a=2
31072: a=1