Bug 243322 - Behavior change on "cat filename | while read varname" construct
Summary: Behavior change on "cat filename | while read varname" construct
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Red Hat Enterprise Linux 4
Classification: Red Hat
Component: bash
Version: 4.5
Hardware: All
OS: Linux
low
medium
Target Milestone: ---
: ---
Assignee: Roman Rakus
QA Contact: Ben Levenson
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2007-06-08 15:43 UTC by paul boin
Modified: 2014-01-13 00:06 UTC (History)
3 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2010-04-06 10:52:27 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)

Description paul boin 2007-06-08 15:43:26 UTC
Description of problem:

We have a script that monitors our shop for static passwords.  It's called from
cron every week.  Worked fine for a long time.  May 27 was good.  June 3 report
only had the first entry printed and then it bailed.

Even now, the script was running fine from console, but broken from cron.

Followed the traditional steps of verifying SHELL and PATH, and spent a long
time printing logs, running with the '-x' option, etc.

Final analysis:

Before the 5/30 upgrade to bash-2.05b-41.7, this job ran fine from cron.  Since
then, no worky.


As a workaround, I can change this:

cat "filename" | while read host
do
 . 
 . 
done

To this:
for host in `cat filename`
do
 . 
 . 
done


Now I'm just wondering what else might be having problems.  We use the "cat |
while read" construct all over the place...

Comment 1 paul boin 2007-06-08 15:44:09 UTC
#!/bin/sh

export SHELL="/bin/sh"
export PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin"
# echo "report $SHELL" >> /tmp/shelllog
# echo "report $PATH" >> /tmp/shelllog


#
# RedHat
#
for OS in rhel3 rhel3-64 rhel4 rhel4-64 rhel5 rhel5-64
do
    if [ ! -d /usr/local/etc/rdist-$OS/Stats/Hosts ]
    then
        echo
        echo "ERROR: /usr/local/etc/rdist-$OS/Stats/Hosts is missing."
        echo
        continue
    fi
    cd /usr/local/etc/rdist-$OS/Stats/Hosts
    ls -t | egrep -v '^1hosts' > /tmp/files.$$
    ls -1 | awk -F'_' '{print $1}' | egrep -v '^1hosts' | sort -u > /tmp/hosts.$$

    # cat "/tmp/hosts.$$" | while read host
    for host in `cat /tmp/hosts.$$`
    do
        file=`grep $host[_] /tmp/files.$$ | head -1`
        grep -a "Password set" $file > /tmp/pwset.$$
        grep -qv root /tmp/pwset.$$
        if [ $? -eq 0 ]
        then
            egrep -q "Mobile PCI Bridge|Mobile CPU|Mobile Pentium|Mobile
Intel|Intel Corporation Mobile" $file
            if [ $? -eq 0 ]
            then
            laptop="*** LAPTOP ***"
            else
            laptop=""
            fi
            ip=`host $host | awk '{print $4}' | head -1`
            echo "$host ($ip)    $laptop"
            echo "================================================="
            grep -v root /tmp/pwset.$$
            echo
        fi
    done
    rm /tmp/files.$$ /tmp/hosts.$$ /tmp/pwset.$$
done




Comment 2 paul boin 2007-06-08 16:04:21 UTC
Well, maybe I'm wasting time, sorry...

I did a "rpm -ivh --force --oldpackage bash-2.05b-41.5.i386.rpm", and then re-ran.

The "cat | while read" is still broken, and the "for variable in" method still
works.

Odd...  What are the chances that bash changed in between good and bad runs, but
it's not the problem?



Comment 3 Roman Rakus 2008-03-25 13:38:01 UTC
cat | while read works for me in version bash-2.05b-41.7, also works in
bash-3.0-19.6.

I have simple script:
#!/bin/bash
cat file.txt | while read text
do
        echo $text
done

and works perfectly. Can you please describe where is the problem? What exactly
means "not working"? It is possible that the problem is in file /tmp/hosts.$$.
But I'm just guessing.
Can you please write more information about your problem?
Thank you.

Comment 4 Roman Rakus 2010-04-06 10:52:27 UTC
Please read bash FAQ. Section E4;
--snip--
Each element of a pipeline, even a builtin or shell function,
runs in a separate process, a child of the shell running the
pipeline.  A subprocess cannot affect its parent's environment. 
When the `read' command sets the variable to the input, that
variable is set only in the subshell, not the parent shell.  When
the subshell exits, the value of the variable is lost. 
--snip--

Closing this one as notabug...


Note You need to log in before you can comment on or make changes to this bug.