[WNYLUG-Users] Burnt by Bash AGAIN!!!!

Joe josephj at main.nc.us
Mon Feb 8 17:02:57 EST 2010


Joe Hoot wrote:
> Hi all,
>
> I don't know if others have had this happen to them.  However, I have run into this 3-4 times now and have been beating my head against the wall (poor wall) attempting to debug this.  I hope my memory will hold up next time so that I'll remember that bash doesn't handle pipes in the way I would want them to.  But I figured I'd toss this out to the list in case anyone else runs into these problems once in awhile and doesn't want to put dents in their wall:
>
> Here's an example of why I was banging the wall:
>
> #!/bin/bash
> #  - numdiscs.sh - script to check /var/log/messages* to see if iSCSI has disconnects and if there
> #                              have been any dm-multipath path failures because of the iSCSI disconnects
> #
> MESSAGES=$(ls /var/log/messages*)
> TMPMNTH=AAA
> TMPDAY=0
> FIRSTROUND=0
>
> printf "Date\tDisconnects\tPath Failures\n"
> printf "=====================================\n"
>
> for MESSAGEFILE in $MESSAGES
> do
>   cat $MESSAGEFILE | grep -e "remaining active paths:" -e "timeout of 10 sec" | while read MSGMONTH MSGDAY rest_of_line
>   do
>      if [ "$MSGMONTH $MSGDAY" != "$TMPMNTH $TMPDAY" ]; then
>         if [ $FIRSTROUND -ne 0 ]; then
>           printf "$TMPMNTH $TMPDAY    \t$NUMDISC\t\t$NUMPATH \n" 
>         fi
>         FIRSTROUND=1
>         TMPMNTH=$MSGMONTH
>         TMPDAY=$MSGDAY
>         NUMDISC=0
>         NUMPATH=0
>      fi
>
>      echo $rest_of_line | grep "timeout of 10 sec" 2>&1 1>/dev/null
>      if [ $? -eq 0 ]; then
>         NUMDISC=`expr $NUMDISC + 1`
>      fi
>      echo $rest_of_line | grep -e "remaining active paths: 1" -e "remaining active paths: 0" 2>&1 1>/dev/null
>      if [ $? -eq 0 ]; then
>         NUMPATH=`expr $NUMPATH + 1`
>      fi
>   done 
>   printf "$TMPMNTH $TMPDAY    \t$NUMDISC\t\t$NUMPATH \n" 
> done
>
> ##### END 
>
> In Bash, the following line spawns a subshell for grep + another subshell for while.  Well, when you spawn a shell, you'll lose your variables for the parent shell.
> In Ksh, this is handled the way I want it to by doing it within the parent shell without spawning subshells (I believe).  So this works the way I would want it to and allow me to use my variables further along in the program.
>
>   cat $MESSAGEFILE | grep -e "remaining active paths:" -e "timeout of 10 sec" | while read MSGMONTH MSGDAY rest_of_line
>
> The easy fix for me was to change the first line to be #!/bin/ksh and all works as expected.
>
>
> Cya,
> Joe
>
> =====================
> Joseph R. Hoot
> Network Penguin
> joe at networkpenguin.com
> GPG KEY:   7145F633
> =====================
>
>
> _______________________________________________
> Users mailing list
> Users at wnylug.org
> http://wnylug.org/mailman/listinfo/users_wnylug.org
>   
Studying this raised some questions and comments for me:

First of all, (although this has no bearing on the main issue) I have no
idea what the script is supposed to accomplish because I don't know
anything about the things it is trying to report on.

Wouldn't export TMPMNTH TMPDAY FIRSTROUND
fix the problem with your loop?

What does grep do with more than one -e argument? Are they treated as an
"or" or an "and"?

Could echo $rest_of_line | grep "timeout of 10 sec" 2>&1 1>/dev/null be
simplified to

echo $rest_of_line | grep -q "timeout of 10 sec"

Could NUMPATH=`expr $NUMPATH + 1` be simplified to

(( NUMPATH++ ))

Maybe your approach is needed to work in older versions of bash. I'm
pretty sure that grep -q is not universal.

Joe





More information about the Users mailing list