1

I'm running a command that writes warnings to stdout, and I want my script to stop on those warnings, so piecing together a lot of stuff I learned here, I have the following...

  warnd=false;
  myLongCommand |
    while IFS= read -r line
    do
      if [[ $line == *"WARNING in ."* ]]; then
          warnd=true;
          echo "found a warning!!!!!"
          break
      fi
      echo $line
    done
    echo WARNING IS $warnd
  if [[ "$warnd" == true ]]; then
      echo "exiting due to warning"
      exit
  else
      echo "no warnings"
  fi

But this doesn't work as I expect. When myLongCommand writes a warning, I see the following echo'd...

found a warning!!!!!

WARNING IS false

no warnings

Why isn't the change to my warnd variable seen after the loop. I've read about scoping of shell script variables, but nothing seems to indicate that the variable inside the loop has a different scope.

Community
  • 1
  • 1
user1272965
  • 2,814
  • 8
  • 29
  • 49
  • 1
    Change `myLongCommand | for;do;done` to `for;do;done < <(mylongcommand)`. Pipes opens a subshell, and when it finishes closes it, causing any variable set in the subshell to be lost. – 123 May 13 '17 at 17:07

1 Answers1

1

You are running the command in a pipe-line and modifying a variable, which does not get effect after the sub-shell created by the pipe-line terminates. Use a proper process-substitution technique with a while-loop,

while IFS= read -r line
do
  if [[ $line == *"WARNING in ."* ]]; then
      warnd=true;
      echo "found a warning!!!!!"
      break
  fi
done< <(myLongCommand)

Worth reading this BashFAQ - 024 - I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates? Or, why can't I pipe data to read?

A simple example quoting from the linked page,

linecount=0

printf '%s\n' foo bar |
while IFS= read -r line
do
    linecount=$((linecount + 1))
done

echo "total number of lines: $linecount"

So ideally the expected value for the lineCount would be 2 but since the variable is updated in a sub-shell created by the pipe-line, the update does not reflect once the sub-shell exits.

FYI, the above small snippet produces an output as

total number of lines: 0
Inian
  • 80,270
  • 14
  • 142
  • 161
  • Thanks. This solution didn't work for me, but it got me on track. (The DUP didn't help me either). I got `syntax error near unexpected token `<'` on that done line. The way I fixed was to wrap everything after the command in curly braces. Thanks for getting me on track! – user1272965 May 13 '17 at 17:23
  • @user1272965: Happy to be of help. You didn't let us know your command, else we could spotted if it had any issues. But my answer was a general way to avoid pipelines when updating variables. – Inian May 13 '17 at 17:25