15.13. Controlling Another Program with ExpectProblemYou want to automate interaction with a full-screen program that expects to have a terminal behind STDIN and STDOUT. SolutionUse the Expect module from CPAN: use Expect; $command = Expect->spawn("program to run") or die "Couldn't start program: $!\n"; # prevent the program's output from being shown on our STDOUT $command->log_stdout(0); # wait 10 seconds for "Password:" to appear unless ($command->expect(10, "Password")) { # timed out } # wait 20 seconds for something that matches /[lL]ogin: ?/ unless ($command->expect(20, -re => '[lL]ogin: ?')) { # timed out } # wait forever for "invalid" to appear unless ($command->expect(undef, "invalid")) { # error occurred; the program probably went away } # send "Hello, world" and a carriage return to the program print $command "Hello, world\r"; # if the program will terminate by itself, finish up with $command->soft_close(); # if the program must be explicitly killed, finish up with $command->hard_close(); DiscussionThis module requires two other modules from CPAN: IO::Pty and IO::Stty. It sets up a pseudo-terminal to interact with programs that insist on using talking to the terminal device driver. People often use this for talking to passwd to change passwords. telnet (Net::Telnet, described in Recipe 18.6 , is probably more suitable and portable) and ftp are also programs that expect a real tty.
Start the program you want to run with
To wait for the program to emit a particular string, use the $which = $command->expect(30, "invalid", "succes", "error", "boom"); if ($which) { # found one of those strings }
In scalar context,
In list context,
Sending
input to the program you're controlling with Expect is as simple as using
When you're finished with the spawned program, you have three options. One, you can continue with your main program, and the spawned program will be forcibly killed when the main program ends. This will accumulate processes, though. Two, if you know the spawned program will terminate normally either when it has finished sending you output or because you told it to stop - for example,
telnet
after you exit the remote shell - call the See AlsoThe documentation for the Expect, IO::Pty, and IO::Stty modules from CPAN; Exploring Expect , by Don Libes, O'Reilly & Associates (1995). |
|