Controlling Another Program with Expect
Problem
You want to automate interaction with a full-screen program that expects to have a terminal behind STDIN and STDOUT.
Solution
Use 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();
Discussion
This 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 Section 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
Expect->spawn
, passing a program name and arguments either ...
Get Perl Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.