Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??
I would like to talk to an external program (midish) from perl using Expect (or Expect::Simple). I want to spawn this program once, keeping the child process loaded while I do other stuff. AFAIK Midish is well-behaved, using STDIN and STDOUT for I/O. However I'm having a hard time getting a reponse reliably after sending a command.

Update 1: I will investigate approaches other than Expect.

Update 2: Zentara's solution using IPC::Open3 is *way* simpler.

My first experiment was a simple command loop:

- get a prompt ("+ready")

- send a command

- get a reply

I thought I would try with Expect::Simple, however some buffering or command-ordering problems arise.

------ test-expect-simple ---- use Modern::Perl; use Expect::Simple; $| = 1; my $obj = Expect::Simple->new({ Cmd => [ midish => '-v'], Prompt => '+ready', DisconnectCmd => 'exit', Verbose => 0, Debug => 0, Timeout => 100 }); sub prompt { print "midish> " } while ( prompt(), my $cmd = <STDIN> ){ exit if $cmd =~ 'quit'; chomp $cmd; $cmd .= "\r"; $obj->send( $cmd ); my @lines = split "\n", $obj->before; splice(@lines, 0, 2); # throw away the first two lines say join "\n", @lines; } __END__ $perl test-expect-simple midish> asdf asdf: no such proc midish> 1234 midish> ffff 3.5: statement or proc definition expected midish> ^C

Comment: I'm not getting the full message after sending a command. Maybe it's a problem with Expect::Simple.

So here is the next try, a command loop using Expect.

------ test-expect-loop ----- use Expect; use Modern::Perl; my $exp = Expect->spawn("midish","-v") or die "Couldn't start program: $!\n"; # don't copy program output to STDOUT $exp->log_stdout(0); $exp->expect(1, '+ready', \&do_cmd); sub do_cmd { map{say "midish: $_"} split "\n", $exp->before; print "enter command >> "; my $cmd = <STDIN>; $exp->send($cmd); exp_continue; } $exp->soft_close(); __END__ program output: $ perl test-expect-loop enter command >> adsfsd midish: midish: adsfsd midish: adsfsd: no such proc enter command >> 1234 midish: midish: 1234 midish: 2.5: statement or proc definition expected enter command >> ffff midish: midish: ffff midish: ffff: no such proc enter command >> exit $

Good, I'm getting output after every command. But my application is structured more like this:

call_to_expect($one_command); execute_other_code(); call_to_expect($another_command); ------ test-expect-unrolled ----- use Expect; use Modern::Perl; my $exp = Expect->spawn("midish","-v") or die "Couldn't start program: $!\n"; # don't copy program output to STDOUT $exp->log_stdout(0); $exp->expect(1, '+ready', \&do_cmd); print_output(); $exp->expect(1, '+ready', \&do_cmd); print_output(); $exp->expect(1, '+ready', \&do_cmd); print_output(); sub do_cmd { print "enter command >> "; my $cmd = <STDIN>; $exp->send($cmd); } sub print_output { map{say "midish: $_"} split "\n", $exp->before; } $exp->soft_close(); __END__ program output: $ perl test-expect-unrolled enter command >> asdf enter command >> 1234 midish: midish: asdf midish: asdf: no such proc enter command >> ffff midish: midish: 1234 midish: 2.5: statement or proc definition expected <hang> ^C $

So, I still have a problem getting a one-to-one correspondence between the command string and the result string.

Any ideas how I could make one call to send a command and get a response, in a way that I can repeat indefinitely? Thanks for reading!

In reply to Getting Call-Response Behavior with Expect by gnosti

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others scrutinizing the Monastery: (7)
    As of 2016-07-29 12:34 GMT
    Find Nodes?
      Voting Booth?
      What is your favorite alternate name for a (specific) keyboard key?

      Results (261 votes). Check out past polls.