1

I want to redirect the output of a for loop to a file and to stdout.

So far I tried this but it actually forks the script :

$ cat myScript.sh
#!/usr/bin/env bash

myVar1=X.Y.Z.T
echo "=> BEFORE THE LOOP : myVar1 = $myVar1"
for IP;do
   myVar1="$IP"
   echo "=> INSIDE THE LOOP : myVar1 = $myVar1"
done 2>&1 | tee -a myFile.log
echo "=> AFTER THE LOOP : myVar1 = $myVar1"

EDIT1 : If I run the script, here is what happens :

$ ./myScript.sh 1.2.3.4 9.8.7.6
=> BEFORE THE LOOP : myVar1 = X.Y.Z.T
=> INSIDE THE LOOP : myVar1 = 1.2.3.4
=> INSIDE THE LOOP : myVar1 = 9.8.7.6
=> AFTER THE LOOP : myVar1 = X.Y.Z.T

The value of myVar1 is not the same in the father process than in the child process.

How can I avoid using a pipe here ?

EDIT0 : After some research in the chapter 20 section 1 of the Advanced Bash-Scripting Guide, I came up with this :

exec 3>&1 1> >(tee -a myFile.log) # backup stdout to file descriptor 3 and then redirect stdout to myFile.log via process substitution
# my shell instructions are here
exec 1>&3 3>&- # restore stdout and close file descriptor 3
SebMa
  • 4,037
  • 29
  • 39
  • There is no forking in your script, the pipe will exec tee and connect its input to the output of the loop. There is also no `myVar` variable in your script. What is the output you get and what is the output you expected ? – bendem Jul 15 '22 at 12:57
  • 1
    @bendem According to [this](https://tldp.org/LDP/abs/html/special-chars.html#PIPEREF), I quote : > A pipe runs as a child process, and therefore cannot alter script variables. – SebMa Jul 15 '22 at 13:12
  • That is correct, tee is a child process of your script. Not a fork, there is a single instance of your script being executed. `tee` does not interpret its input, it only outputs what it is given to a file and to stdout. – bendem Jul 15 '22 at 13:16
  • 1
    @bendem I thought what was on the left on the `|` was also a child process, is this correct ? – SebMa Jul 15 '22 at 13:29
  • @bendem I have removed var2 and added the output of the script. Please take a look at my EDIT1. – SebMa Jul 15 '22 at 18:21
  • Ok, you taught me something new here. I did not know that piping a command to anything meant that the whole pipeline was moved to a subprocess. You are correct. By piping the loop, you are moving it to a child process, which makes changing outer variables impossible. FD swapping is indeed a good solution for your problem (and this is why complex problems should not be solved with bash, too much surprising behavior like this). – bendem Jul 18 '22 at 08:23
  • @bendem Actually, there are two child processes created here, one for each side of the `|`. But bash is powerful enough, we just need to master it :-) – SebMa Jul 18 '22 at 08:30

0 Answers0