Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Communicate with child process via stdin, stdout

by Anonymous Monk
on Nov 20, 2011 at 00:47 UTC ( [id://939017]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'd like to write a Perl script, that would start another process (command line) and then communicate with it via its stdout and stdin. Can you please help me with starting code. I've tried with IPC::Open2 , but it doesn't work.... Thanks in advance, regards, Robert Rozman.

Replies are listed 'Best First'.
Re: Communicate with child process via stdin, stdout
by ww (Archbishop) on Nov 20, 2011 at 01:26 UTC
    Hi, Robert and welcome to the Monastery.

    You may want to read the site's FAQs and one or both of these: On asking for help and How do I post a question effectively?. We strive to provide a learning enviroment... not a codewriting service.

    But, for starters on the problem that brought you here, you may wish to read about system, exec, backticks et al. And feeding a fairly obvious selection of keywords to Super Search will provide you with a rather extensive list of nodes on the very topic.

    Obligatory correction: "doesn't work" is NOT a useful description of a failure. What happened? What warnings or errors messages did you receive? What's your code look like? (What you post should demonstrate your problem, repeatably; but as minimal as possible while satisfying the first constraint.) And what process -- a shell process, an executable, what?

    Give us a chance to provide useful help by providing those elements, and you're virtually guaranteed to get responsive replies, probably quicker than you expect.

      Hi,

      thanks for response and yes, I'm sorry - wasn't specific enough....

      Another try. I have command line utility that communicates with central software router under LMCE system. Whatever script receives from router it sends to stdout and whatever it receives on stdin, will be sent to router.

      Therefore I need to have two way communication with that script from my Perl app.

      Here is the code I'm trying, but get nothing (utility works from command line - it sends string to stdout) :
      #! /usr/bin/perl use warnings; use strict; use IPC::Open2; my $pid = open2 my $out, my $in, "/usr/pluto/bin/DCE-Whisperer -d 38 - +r 192.168.0.51"; die "$0: open2: $!" unless defined $pid; #print $in "PING"; my $sum=undef; while (1) { $sum = <$out>; if ($sum) { print ("Got from DCERouter(out): $sum\n") ; print $in "reply txt OK\n"; $sum=undef; }; } ; close $in or warn "$0: close: $!"; close $out or warn "$0: close: $!";


      Thanks in advance for any help...

      regards,

      Rob.

        I don't have a copy of DCE-Whisperer to test with, so take this with a grain of salt...

        If I change the child process to /bin/cat, I can get the script to run if I uncomment the print $in AND change it to

        print $in "PING\n";

        which works because (in this case) it flushes the buffer for $in. You could also flush the $in buffer with

        $|=1;

        depending on the child process - for example cat doesn't work without a "\n".

        However, you may be running into buffering issues with DCE-Whisperer as well. As the documentation for IPC::Open2 mentions, "The big problem with this approach [that is, IPC::Open2 itself] is that if you don't have control over source code being run in the child process, you can't control what it does with pipe buffering.... The IO::Pty and Expect modules from CPAN can help with this, as they provide a real tty (well, a pseudo-tty, actually), which gets you back to line buffering in the invoked command again."

Re: Communicate with child process via stdin, stdout
by zentara (Archbishop) on Nov 20, 2011 at 12:43 UTC
    I've tried with IPC::Open2 , but it doesn't work

    Are you on Microsoft Windows? Try this example if you are on a unix style system.

    #!/usr/bin/perl use warnings; use strict; use IPC::Open3; use IO::Select; #interface to "bc" calculator my $pid = open3(\*WRITE, \*READ,\*ERROR,"bc"); my $sel = new IO::Select(); $sel->add(\*READ); $sel->add(\*ERROR); my($error,$answer)=('',''); while(1){ print "Enter expression for bc, i.e. 2 + 2\n"; chomp(my $query = <STDIN>); #send query to bc print WRITE "$query\n"; foreach my $h ($sel->can_read) { my $buf = ''; if ($h eq \*ERROR) { sysread(ERROR,$buf,4096); if($buf){print "ERROR-> $buf\n"} } else { sysread(READ,$buf,4096); if($buf){print "$query = $buf\n"} } } } waitpid($pid, 1); # It is important to waitpid on your child process, # otherwise zombies could be created.

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      waitpid($pid, 1); # It is important to waitpid on your child process, # otherwise zombies could be created.

      As an aside, waitpid at the end of a script (as you have it here) is not important or necessary. Nothing bad will happen without it, as the OS will automatically reap any zombies when their parent process has gone away. In other words, zombies can only exist as long as the parent is still alive.

        Dunno...   I have encountered zombies with a parent-PID of “1.”   Dunno why it happens and I don’t think it should, but, “there they were.”   I have only seen it in a FastCGI process (owned by Plack), but I have seen it nonetheless.   It probably is a good idea, then, to clean up after oneself explicitly.   If you rendezvous with every child-process that you created, and show them to their graves, then everything is nice and neat and predictable.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://939017]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (6)
As of 2024-03-28 10:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found