2

I have redirected the output of the command which returns some times 2 rows, 5 rows.. 100 rows etc in the file.. and i will use this file in if condition later to check some other conditions..

Strange thing is - I need to execute the script multiple times to get the data as expected.. if I execute the script first time it simply return nothing.. Please can you help why this is not giving the expected result in the first run

The code is for AIX and is as follows:

df -gt | grep /home/prods/db2/ > /tmp/DISKREQ.TMP
if [[ $? -eq 0 ]]; then
        chmod 777 /tmp/DISKREQ.TMP
        cat /tmp/DISKREQ.TMP | awk '{print$6}' | awk 'length($0) == 22' > /tmp/DISKREQ.TMP
        cat /tmp/DISKREQ.TMP | while read line
        do
                        FSIZE_DISKREQ=`df -g | awk '$7 == "'$line'" {print $3;}'`
                        if [[ $FSIZE_DISKREQ -lt 2 ]]; then
                        echo
                         echo " Instance Home Directory $line = $FSIZE_DISKREQ "
                        else
                        echo
                                echo " Instance Home Directory $line "
                        fi
        done
else
echo
        echo "No Instance Home directory Mounted"
fi
  • @Roaima - it's AIX – RenukaKC Oct 8 '15 at 17:23
  • 3
    Are you sure that the shell doesn't wipe the file for writing before the cat | awk | awk pipe starts reading from it? – Philippe Gauthier Oct 8 '15 at 19:30
  • To put PhilippeGauthier's point more finely -- use different filename for your temporary (DISKREQ.TMP) files so that you're not clobbering them. – Jeff Schaller Oct 8 '15 at 23:31
2
cat /tmp/DISKREQ.TMP | awk '{print$6}' | awk 'length($0) == 22' > /tmp/DISKREQ.TMP

The components of a pipeline are executed in parallel. This line thus executes three commands in parallel:

  • cat /tmp/DISKREQ.TMP
  • awk '{print$6}'
  • awk 'length($0) == 22' > /tmp/DISKREQ.TMP

The first command is opening /tmp/DISKREQ.TMP for reading. The third command is truncating /tmp/DISKREQ.TMP before it does anything else. Depending on timing, cat may or may not have time to read at least the beginning of the file.

Solution: don't write to the same file as the input. (There are more complex and more fragile solutions that let you reuse the name; I'm not going to give one because there's no point in doing something complicated here.)

df -gt | grep /home/prods/db2/ > /tmp/DISKREQ.TMP
if [[ $? -eq 0 ]]; then
    cat /tmp/DISKREQ.TMP | awk '{print$6}' | awk 'length($0) == 22' > /tmp/DISKREQ2.TMP
    cat /tmp/DISKREQ2.TMP | while read line
    …

(Don't use chmod 777. This never solves anything but can create problems.)

You don't need all these temporary files though, so you can completely sidestep the problem by getting rid of them. Just pipe the awk chain directly into the while loop to get rid of the second temporary file. I've also gotten rid of the useless uses of cat and combined the two awk scripts into one.

df -gt | grep /home/prods/db2/ > /tmp/DISKREQ.TMP
if [[ $? -eq 0 ]]; then
    </tmp/DISKREQ.TMP awk 'length($6) == 22 {print $6}' | while read line
    do
    …

You can even get rid of awk altogether and do the filtering in the while read loop; I'll leave that as an exercise to the reader.

To get rid of the first temporary file requires changing the logic a bit. The while loop body won't run anyway if grep doesn't find anything, since it'll get zero lines to work on, but you need some logic to display the message in that case. You can use an END directive in awk.

df -gt | grep /home/prods/db2/ |
awk 'length($6) == 22 {print $6}
     END {if (NR==0) print "No Instance Home directory Mounted"}' |
while read line; do …

You can combine the grep call with awk. (Exercise to the reader.) Or you can do the whole filtering in the shell. I assume that /home/prods/db2/ will always be the start of the sixth column.

found=0
df -gt |
while read device total used available percent mountpoint; do
    [[ $mountpoint == /home/prods/db2/* ]] || continue
    ((++found))
    [[ ${#mountpoint} -eq 22 ]] || continue
    …
done
if ((found == 0)); then echo "No Instance Home directory Mounted"; fi
  • it is working.. Thank you so much for detailed explanation.. – RenukaKC Oct 9 '15 at 7:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.