Networker

Re: [Networker] Still can't do this in Perl

2004-11-24 12:47:50
Subject: Re: [Networker] Still can't do this in Perl
From: Darren Dunham <ddunham AT TAOS DOT COM>
To: NETWORKER AT LISTMAIL.TEMPLE DOT EDU
Date: Wed, 24 Nov 2004 10:11:53 -0800
> #!/usr/bin/perl
>
> # Begin fix
> $result = open(CHILD, "-|");
> # End fix

> die "Couldn't open pipe to subprocess" unless defined($result);
> open (ADM, "|/usr/sbin/nsradmin -s server") or
>    die "Couldn't open pipe to nsradmin.\n";

Umm, that is *NOT* the way I would write that.  You're forking off a
child, but you give no indication that you're running multiple threads
in here.  Becuase you don't run a conditional on the $result, you're
running nsradmin twice!  Once in the parent, and again in the child.

Why are you doing this?

When you run this program, don't you get warnings and errors?  I do when
I try it...

$ perl -w /tmp/perl2
Use of uninitialized value at /tmp/perl2 line 11.
Use of uninitialized value at /tmp/perl2 line 11.
Read on closed filehandle <CHILD> at /tmp/perl2 line 15.
Use of uninitialized value at /tmp/perl2 line 11.
Use of uninitialized value at /tmp/perl2 line 11.
                        type: NSR;
                        [....]


> print ADM "print type: NSR $ARGV[0]; name: $ARGV[1]\n";
> close ADM;
>
> # Begin fix
> while(<CHILD>)
> {
>   push @list, $_;
> }
> close(CHILD);
>
> foreach (@list)
> {
>    print $_;
> }
> # End fix
>
> NOTES: A couple of things here. What was throwing me off was the fact
> that I had "|/usr/sbin/nsradmin -s server -i")
> and as a result, it was expecting a file to be passed in.

I think all of our examples use '-i -'.  By specifying the file as "-",
it reads from stdin.

> Apparently,
> you can get away with that in the Bourne shell, but not in Perl. So, by
> removing the '-i', that solved that. However, the next problem I ran
> into was that while the output of the script was getting dumped to the
> console, I was not able to capture that output or save it so I could
> then process it -- something I'd like to be able to do. I resolved that
> by adding the lines listed between the "Begin fix" and "End fix"
> remarks. At the end, I'm not doing anything but just dumping the same
> output, but I could parse it, process it, whatever I want since I now
> have the output captured in @list. HOWEVER, the one thing I'd like to be
> able to do is to turn off the output to the console that gets created
> from the line:
>
> print ADM "print type: NSR $ARGV[0]; name: $ARGV[1]\n";

That's because you're running it *twice*.  You're running it once in the
child (which is later read by the parent), and you're running it again
in the parent (which is printed to STDOUT).

You need to understand that the special open you're doing there is the
same as calling fork() in your program.  That generally requires
conditionals so that you do some work in the parent and some in the
child.


Can I ask why you're opposed to using Open2 or Open3?  They make work
like this much simpler...

#!/usr/bin/perl -w
use strict;

use IPC::Open2;
my $pid = open2(\*RDRFH, \*WTRFH, "nsradmin -i -");

# send some commands to nsradmin.
print WTRFH "show name\n";
print WTRFH "print type:NSR client\n";
close WTRFH;

# get the results.
my @output = <RDRFH>;

print @output;

--
Darren Dunham                                           ddunham AT taos DOT com
Senior Technical Consultant         TAOS            http://www.taos.com/
Got some Dr Pepper?                           San Francisco, CA bay area
         < This line left intentionally blank to confuse you. >

--
Note: To sign off this list, send a "signoff networker" command via email
to listserv AT listmail.temple DOT edu or visit the list's Web site at
http://listmail.temple.edu/archives/networker.html where you can
also view and post messages to the list. Questions regarding this list
should be sent to stan AT temple DOT edu
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=