Variable not getting set when calling sub with tee. Is this expected behaviour?

Hi,

Is this expected behavior when calling a sub using tee?

Test script is as below:

$: cat tee.bash
#!/bin/bash
#

export x=YES
export LOG=/tmp/setvar.OUT
setvar ()
{
  echo "Hello World"
  x=NO
}

cat /dev/null > $LOG
echo "## STARTING with x=YES | x=${x}"
echo "calling setvar TO set x to NO"
setvar
echo "## RAN setvar | x should be NO | x=${x}"
x=YES
echo "## RESETTING x to YES | x=${x}"
echo "calling setvar with tee"
setvar | tee -a $LOG
echo "## RAN setvar WITH tee -a | x should be NO BUT IT ISN'T. IS THIS EXPECTED BEHAVIOR? | x=${x}"

RUNTIME of the tee.bash script

$: ./tee.bash
## STARTING with x=YES | x=YES
calling setvar TO set x to NO
Hello World
## RAN setvar | x should be NO | x=NO
## RESETTING x to YES | x=YES
calling setvar with tee
Hello World
## RAN setvar WITH tee -a | x should be NO BUT IT ISN'T. IS THIS EXPECTED BEHAVIOR? | x=YES
$:
$: cat /tmp/setvar.OUT
Hello World
$:

This is just an excerpt of the script. The whole sub has several echo commands that I am wanting to append to a log file.

At the moment, because of this behavior, I am just doing the tee -a inside the sub instead of when the sub is called. That is, I have it as below in the sub.

echo "Hello World" | tee -a ${LOG}

Please advise. Thanks.

Your problem is the pipe; bash and other shells run each part of the pipe in a sub shell, a clone of the main shell. Variables in the main shell are copied to the sub shell, but not vice versa.
See the following little exercise:

$ x=YES; { echo "inherited x=$x"; x=NO; echo "new x=$x"; }; echo "main x=$x"
inherited x=YES
new x=NO
main x=NO
$ x=YES; { echo "inherited x=$x"; x=NO; echo "new x=$x"; } | cat; echo "main x=$x"
inherited x=YES
new x=NO
main x=YES

The command group runs in the subshell when piped.
In your case the function is forced to run in a sub shell.

A work-around is to redirect the function's output to a temp file:

tmpfile=/tmp/tmpfile.$$
setvar > $tmpfile; < $tmpfile tee -a $LOG
3 Likes