Operating System - HP-UX
1819899 Members
2560 Online
109607 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
Patrick Ware_1
Super Advisor

Re: Need help with for loop with while read

Thanks for your replies!

One question:

What is the purpose of the following?:


exec < /dev/null

James R. Ferguson
Acclaimed Contributor

Re: Need help with for loop with while read

Hi (again):

> What is the purpose of the following?: exec < /dev/null

This sets STDIN to '/dev/null'.

Regards!

...JRF...
Patrick Ware_1
Super Advisor

Re: Need help with for loop with while read

Ok, I think I answered my own question. Please forgive me, as I am still learning quite a bit about scripting. I have tried the format, and it immediately ends with no output.
Patrick Ware_1
Super Advisor

Re: Need help with for loop with while read

Ok folks, I got it working. My mistake was a typo in the name of the input file. Points are being awarded!

Thanks!
Patrick Ware_1
Super Advisor

Re: Need help with for loop with while read

James R. Ferguson
Acclaimed Contributor

Re: Need help with for loop with while read

Hi (again) Patrick:

As Dennis stated, you could use 'ssh -n' to redirect STDIN from /dev/null. This is probably a more clear and more standard technique of the two he showed. Of course, this assumes that your 'ssh' setups use public keys so that no password prompts are requested.

Regards!

...JRF...

Patrick Ware_1
Super Advisor

Re: Need help with for loop with while read

Thank you! I was writing another script, where I ran into that exact problem, and the ssh -n solved it for me!
Dennis Handly
Acclaimed Contributor

Re: Need help with for loop with while read

>Here are the results: www.unix.com

You probably should update that URL to include the obvious ssh host-name -n solution.

>JRF: ... technique of the two he showed.

I showed 3.
James R. Ferguson
Acclaimed Contributor

Re: Need help with for loop with while read

Hi:

> Dennis: >JRF: ... technique of the two he showed. >> Dennis: I showed 3.

Touche, Dennis, yes indeed you did show three (3)...my apologies :-} ...and regards!

Regards!

...JRF...