Get coprocess output into var

This is probably a simple one for the wise.

I have just started using a coprocess (first time) in order to facilitate telnet'ing from inside a shell script. It's working, but when I run a remote command I need to get the output into a local variable, but alas my kung-fu is weak.

#! /usr/bin/ksh                                        |
                                                       |
DELAY=1                                                | <= Sleep delay
UNAME=d269836                                          | <= Login credentials
PWORD=my_password                                      |
SUPWORD=su_password                                    | <= su login credentials (i know i know)
                                                       |
exec 4>&1                                              | <= Make cop output > stdout
telnet mmm2 >&4 2>&4 |&                                | <= Start cop
sleep $DELAY                                           |
print -p $UNAME                                        | <= Login
sleep $DELAY                                           |
print -p $PWORD                                        |
sleep $DELAY                                           |
print -p su -                                          | <= Go su on remote host
sleep $DELAY                                           |
print -p $SUPWORD                                      |
sleep $DELAY                                           |
print -p clear                                         | <= Clear telnet junk from screen
sleep $DELAY                                           |
print -p cO=\$\(/my_command \)\>/dev/null 2\>/dev/null | <= This *will* put the figure into $cO, but I think $cO 
sleep $DELAY                                           |    is local to the telnet session on remote host?
echo $cO                                               | <= Therefore the output from this is nothing.    
sleep $DELAY                                           |
 

I used the sample supplied by Perderabo to construct this (very handy, props to Perderabo!! => http://www.unix.com/shell-programming-scripting/11359-need-script-passwd-cant-use-expect-tool-3.html#post40791), and I basically understand the idea of coprocesses, but I just can't get succinct output back into a local variable. I have also tried running my_command in background (and not) followed (and preceded) by a "read -p cO" but the read just sits there and halts the script until ^C.

Any takers?

Bump! Hardly anyone has even read this... wrong forum?

Tread softly, for you tread on Rule #4.

I have to admit I generally avoid the use of co-processes due to their complexity and the convenient alternatives such as expect (instead of co-processes) and ssh (instead of telnet). Any reason why you particularly need to use them here... a learning exercise? My telnet on HP-UX doesn't seem to want to deal in stdin/stdout/stderr anyway, it seems to talk directly to my tty... I'll try elsewhere too.

oh, oops. Actually I more stomped on it since I also sent a PM to someone in-the-know...

The host script which needs to use this snippet does most of its work with ssh, but one particular remote host does not have ssh (and wont, before this project is due) hence the telnet.

I may be able to try expect; but I'm not sure how it will go logging in + going to su before running my_command on remote host...

I don't know how to make ksh behave the way you want. The best I can come up with is to send a command to the remote system to run a command and put the output in a remote file. Then use ftp to retrieve the file and examine the contents. It's not pretty but it works in environments where freeware is not available.

This stuff is much easier with openssh and that is what I do these days. No complex co-process or exec statements are needed. And it's much more secure.

expect is perfect for all of the above. Consider using autoexpect to record a manual session first and generate a script... which you can then modify to trim out the excessively verbose regex it generates.

Thanks all, I'll try expect/autoexpect and see what I can come up with. Sorry for being pushy... it's a side effect of my stupidity.

No worries... just so you know, there are those among us who periodically search for "unanswered questions", so if you just wait, someone who knows the answer should pick it up eventually. By bumping the post with a reply you prevent it from being found by such a query.

Your original code seems to work fine more-or-less if you just remove the redirection to file descriptor 4 (by doing this you are taking it away from &p) and then use read -p to read the output into a variable, perhaps in a while loop. You can use some logic in the while loop to recognise the line of output you're expecting.

The only problem is... if for some reason it fails to log in, or you don't find the output you're expecting, the while read -p variable loop will block waiting for more input from the pipe, so you'd need some kind of timeout facility (another background process?) to prevent your script running forever.

Try this:

telnet $HOSTNAME |&
sleep $DELAY
print -p $UNAME
sleep $DELAY
print -p $PWORD
sleep $DELAY
print -p uptime
sleep $DELAY
while read -p UPTIME
do
        print "read line:$UPTIME" | cat -vet
        if [[ "$UPTIME" = *average:* ]]
        then
                print found the uptime
                break
        fi
done
print -p exit
print the uptime is $UPTIME

The trouble with that approach is that the remote host could have a login banner. Our hosts do and it's about 15 lines of lawyer language. But every now and then we encounter a host without the approved message or with an older version of the message. Then there could be a /etc/motd. Everybody had to give me an account on any company box so that I could verify security issues. But I wound up with 6 different prompts. Stuff like this is what you encounter when you are automating access to hundreds of systems. The flying blind approach works in the face of these issues.

Yep, I know exactly what you mean... although that shouldn't hinder my solution above unless the uptime output doesn't contain "average:". I had the same problem as you with a large number of systems and expect, just trying to find regex that matched the various "password:", "Password:", "password: ", etc. and shell prompts was a challenge. Sometimes it's simpler to just issue a PS1=expectshellprompt: or similar as the first command!