Operating System - HP-UX
1748123 Members
3176 Online
108758 Solutions
New Discussion юеВ

Need help with for loop with while read

 
SOLVED
Go to solution
Patrick Ware_1
Super Advisor

Need help with for loop with while read

Hello,

The code below pulls printer information from a three-column file (set by the ${MULTIFILE} variable at the end), that has the printer queue name, IP, and type of printer. It is supposed to use this info to add the printers in the list to one, or more servers . The input file (${MULTIFILE} variable) looks like this:

queuename1 10.10.10.1 hp
queuename2 10.10.10.2 xerox
queuename3 192.168.1.3 hp

This is also the info that feeds the following:

while read QNAME PRTIP PTYPE


The problem I am running into is that it only executes on the first row of the input file, and doesn't go down the input file at all, and I believe this is due to the ${HNAME} variable, which is for the server. How would I make it so that I can have the list of printers installed on multiple servers?

Here is the code:

[CODE]

echo "Enter server host names separated by a blank space. ex.(server1 server2 server3):"
read HNAME
continue ;;
*) add_multiple_printer_func
exit ;;

while read QNAME PRTIP PTYPE
do
for i in $HNAME
do
if [ "$PTYPE" = "hp" -o "$PTYPE" = "Hp" -o "$PTYPE" = "HP" ] ; then
PTYPE=257
elif [ "$PTYPE" = "xerox" -o "$PTYPE" = "Xerox" -o "$PTYPE" = "XEROX" ] ; then
PTYPE=9991
elif [ "$PTYPE" = "unknown" -o "$PTYPE" = "Unknown" -o "$PTYPE" = "UNKNOWN" ] ; then
PTYPE=9991
fi
if [ "$HNAME" = localhost ]
then
echo "Canceling print jobs for $QNAME on $HNAME"
for j in `lpstat -o | grep -w $QNAME" | awk '{print $1}'`
do
echo ${j}
cancel ${j}
done
/opt/hpnp/bin/removequeue -q$QNAME
echo
echo "/opt/hpnp/bin/addqueue -i $PTYPE -q $QNAME -h $PRTIP"
echo
/opt/hpnp/bin/addqueue -i $PTYPE -q $QNAME -h $PRTIP ; lpstat -p | grep $QNAME
# echo "Sending test print to printer"
# print "Printer succssfully installed on $HNAME" | lp -d $QNAME
else
echo $i
echo "--------------------------------------------------------"
echo "Canceling print jobs for $QNAME on $i"
for j in `ssh ${i} "lpstat -o | grep -w $QNAME" | awk '{print $1}'`
do
echo ${j}
echo "ssh ${i} cancel ${j}"
ssh ${i} cancel ${j}
done
fi
done
ssh $i "lpshut ; sleep 02 ; /opt/hpnp/bin/removequeue -q$QNAME ; sleep 02"
echo
echo "ssh $i /opt/hpnp/bin/addqueue -i $PTYPE -q $QNAME -h $PRTIP"
echo
ssh $i "/opt/hpnp/bin/addqueue -i $PTYPE -q $QNAME -h $PRTIP ; lpsched ; lpstat -p | grep $QNAME"
done < ${MULTIFILE} 2> tlg_printer.log 1>&2
sleep 04

[/CODE]

Here is the output:


--------------------------------------------------------
Canceling print jobs for queuename1 on server1
lpshut: scheduler not running
queuename1 does not exist

ssh server1 /opt/hpnp/bin/addqueue -i 257 -q queuename1 -h 10.10.10.1

queuename1 added to spooler.
scheduler is running
printer queuename1 is idle. enabled since Apr 8 01:18


After this output, it ends, and doesn't do the other printers.
18 REPLIES 18
James R. Ferguson
Acclaimed Contributor

Re: Need help with for loop with while read

Hi Patrick:

You would see the behavior you describe if your input ("MULTIFILE") was really one long set of fields instead of three (3) fields per line.

When doing reads, I like:

...

while read QNAME PRTIP PTYPE X
do
...

Now, if necessary you can test and handle cases where there are _more_ than three fields.

Regards!

...JRF...
Patrick Ware_1
Super Advisor

Re: Need help with for loop with while read

I'm sorry, I don't quite follow. Maybe I need to step away to lunch, and come back and read what you told me.
James R. Ferguson
Acclaimed Contributor

Re: Need help with for loop with while read

Hi (again):

> I'm sorry, I don't quite follow.

Well, for that matter, the first few lines of code are part of a 'case' statement, albeit incomplete.

Are you building your "MULTIFILE" file from that logic?

Regards!

...JRF...
Patrick Ware_1
Super Advisor

Re: Need help with for loop with while read

The case statemente has a first part, and I didn't add it here. I don't think it will much difference, but here it is:

echo "Do you want to install these printers to the standard list of servers?"
echo "THIS COULD TAKE A WHILE!!"
print -n "Enter 'y' or 'n':"
read CHOICE
case "$CHOICE" in
y|yes|Yes) HNAME=`cat servers.txt`
continue ;;
n|no|No) echo
echo "Enter server host names separated by a blank space. ex.(server1 server2 server3):"
read HNAME
continue ;;
*) add_multiple_printer_func
exit ;;
James R. Ferguson
Acclaimed Contributor

Re: Need help with for loop with while read

Hi (again) Patrick:

I would suggest running your script with your data having done:

# sh -x scriptname 2>&1

...to trace the output.

Regards!

...JRF...
Patrick Ware_1
Super Advisor

Re: Need help with for loop with while read

I actually output to a logfile from inside the script:

2> printer.log 1>&2

That's where I got the output from.
James R. Ferguson
Acclaimed Contributor

Re: Need help with for loop with while read

Hi (again) Patrick:

> I actually output to a logfile from inside the script:

You missed my suggestion. By running with 'set -x' or doing:

# sh -x script 2>&1

...you will trace the line-by-line execution of your script.

Regards!

...JRF...
Patrick Ware_1
Super Advisor

Re: Need help with for loop with while read

Since it is easier visually to see the trace at this location, I put it here:

http://www.unix.com/shell-programming-scripting/106734-need-help-loop-while-read.html#post302305342

Please be aware that I have functions in this script, and the whole script is 366 lines total, which is why I haven't posted it. The part of the script I have posted is one of the functions that is called from the main menu function.
Dennis Handly
Acclaimed Contributor
Solution

Re: Need help with for loop with while read

>while read QNAME PRTIP PTYPE
>The problem I am running into is that it only executes on the first row of the input file

The first thing you could do is to throw everything away in your while loop and just print $QNAME $PRTIP $PTYPE. This should show you can read the whole file. (TonyFullerMalv's suggestion)

The next thing you should do is gradually add back the contents of loop.

You'll come to the conclusion that you have been stabbed in the back by the remsh/ssh habit of eating up stdin. You'll need to use "remsh hostname -n" or "ssh hostname -n". Or you can redirect stdin to /dev/null:
ssh ... < /dev/null

Or you could possibly use a hammer and stop this in its tracks by this design pattern:
while read X Y Z; do
(
exec < /dev/null
...
)
done < file