tags:

views:

2570

answers:

4

Please explain to me why the very last "echo" statement is blank? I expect that it was incremented in the while loop to a value of 1:

#!/bin/bash
OUTPUT="name1 ip ip status" # normally output of another command with multi line output

if [ -z "$OUTPUT" ]
then
        echo "Status WARN: No messages from SMcli"
        exit $STATE_WARNING
else
        echo "$OUTPUT"|while read NAME IP1 IP2 STATUS
        do
                if [ "$STATUS" != "Optimal" ]
                then
                        echo "CRIT: $NAME - $STATUS"
                        echo $((++XCODE))
                else
                        echo "OK: $NAME - $STATUS"
                fi
        done
fi

echo $XCODE

I've tried using the following statement instead of the ++XCODE method

XCODE=`expr $XCODE + 1`

and it too wont print outside of the while statement. I think I'm missing something about variable scope here but the ol' man page isnt showing it to me.

+1  A: 

Where do you initialize XCODE to something that can be incremented?

Paul Tomblin
I've tried to throw an "XCODE=0" at the top of the code, outside of the while statement
Matt P
Without the cruft, it works for me.#!/bin/bashfor i in 1 2 3 4 5; do echo $((++XCODE))doneecho "fin:" $XCODEI think your problem has nothing to do with variable scoping and everything to do with what's happening in the while.
Paul Tomblin
Agreed.. it seems like it has to do with the "while read" loop?
Matt P
+1  A: 
 #!/bin/bash
 OUTPUT="name1 ip ip status"
+export XCODE=0;
 if [ -z "$OUTPUT" ]
----

                     echo "CRIT: $NAME - $STATUS"
-                    echo $((++XCODE))
+                    export XCODE=$(( $XCODE + 1 ))
             else

echo $XCODE

see if those changes help

Kent Fredric
When doing this, I now get a "0" to print for the last echo statement. however I expect the value to be 1 not zero. Also, why the use of export? I assume that forces it into the environment?
Matt P
+4  A: 

Because you're piping into the while loop, a sub shell is created to run the while loop. Now this child process has it's own copy of the environment and can't pass any variables back to its parent (as in any unix process).

Therefore you'll need to restructure so that you're not piping into the loop. Alternatively you could run in a function for example and echo the value you want returned from the sub process.

http://tldp.org/LDP/abs/html/subshells.html#SUBSHELL

pixelbeat
Makes sense.. Thanks. Looks like the function is the way to go for me.
Matt P
+10  A: 

The problem is that processes put together with a pipe are executed in subshells (and therefore have their own environment). Whatever happens within the while does not affect anything outside of the pipe.

Your specific example can be solved by rewriting the pipe to

while ... do ... done <<< "$OUTPUT"

or perhaps

while ... do ... done < <(echo "$OUTPUT")
mweerden
Brilliant. I had not seen the < < syntax before, so shall have to read up on it, but this works a treat. It feels odd to have the input command at the end rather than the beginning, but it works.
Jonathan