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

i'm trying to script some backup software (BRU Server, if you must know), and the only way to use said software, unfortunately, is through an interactive shell, so I'm using IPC::Run:
# start the ipc $h = start \@cmd, \$in, \$out ; # send login info, keep reading until shell prompt $in = "$password\n" ; pump $h until $out =~ /BRU Server >/i ; # do what we need to do $in = "backup -some -params\n" ; pump $h until $out =~ /BRU Server >/i ; print "Output:\n$output"; # and, we're done here $in = "exit\n" ; pump $h while length $in; finish $h or die "oh crap: $?";
now, this will work, BUT in the case that one of these commands causes the program im talking to to suddenly die, it will keep pump()ing because it will never get the next prompt ("BRU Server >")...how can i tell it to wait for that prompt OR until the program dies?

and it bears mentioning that I can't really set a timeout on the "backup" command, since its an automated backup of variable size, so it could take anywhere from 30 seconds to i dont know how long.

i'd appreciate any help anyone can give me.

Replies are listed 'Best First'.
Re: IPC::Run and start(); pump(); finish()
by kwaping (Priest) on Nov 10, 2005 at 18:46 UTC
    Is there any error message when the program being pumped dies? If so, maybe you could do something like this:
    pump $h until ($out =~ /(BRU Server >)|(error message here)/i);
Re: IPC::Run and start(); pump(); finish()
by BrowserUk (Patriarch) on Nov 10, 2005 at 19:04 UTC

    If you can pursuade IPC::Run to give you the pid of the process, then you could use kill 0, pid; as part of your pump loop to check if the process is still running.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      good idea..now i just need to figure out HOW to get the proc id from it. ive already fired off an email to the module's author :)

        A quick deco at the source on cpan suggests that this is a hash-based class(ish) thing.

        The first thing I would try is dumping the object return by your call to start() using Data::Dumper and look for something obvious, like a key called PID.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: IPC::Run and start(); pump(); finish()
by Anonymous Monk on Nov 14, 2005 at 16:45 UTC
    the IPC::Run->signal() function seems to be able to grab the pid:
    sub signal { my IPC::Run $self = shift ; local $cur_self = $self ; $self->_kill_kill_kill_pussycat_kill unless @_ ; Carp::cluck "Ignoring extra parameters passed to kill()" if @_ > 1 +; my ( $signal ) = @_ ; croak "Undefined signal passed to signal" unless defined $signal ; for ( grep $_->{PID} && ! defined $_->{RESULT}, @{$self->{KIDS}} ) +{ _debug "sending $signal to $_->{PID}" if _debugging; kill $signal, $_->{PID} or _debugging && _debug "$! sending $signal to $_->{PID}" ; } return ; }
    However, I'm not sure how (or if) I can do the same thing from my script...im afraid i may have to modify the module itself, and even then im not totally sure what to do.

      I think I would be tempted to try modifying IPC::Run->signal() to return the result of kill:

      sub signal { my IPC::Run $self = shift ; local $cur_self = $self ; $self->_kill_kill_kill_pussycat_kill unless @_ ; Carp::cluck "Ignoring extra parameters passed to kill()" if @_ > 1 +; my ( $signal ) = @_ ; my $rv; croak "Undefined signal passed to signal" unless defined $signal ; for ( grep $_->{PID} && ! defined $_->{RESULT}, @{$self->{KIDS}} ) +{ _debug "sending $signal to $_->{PID}" if _debugging; $rv = kill $signal, $_->{PID} or _debugging && _debug "$! sending $signal to $_->{PID}" ; } return $rv; }

      and then use that within your pump loop with a parameter of 0;

      pump $h while $h->signal( 0 ) and $out !~ /BRU Server >/i;

      That ought to terminate the loop if the process could not be signalled (has died).

      Obviously untested, but if it works, you could suggest the modification to the maintainer.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.