Caleb Cushing's Blog

Simple scripting CLI with Expect.pm

Expect is use primarily for sending Input to Command Line programs that Prompt and wait for input. For starters you’ll need an executable script and I’ve pasted one that I got elsewhere for a demo.

#!/usr/bin/env perl
# slightly modified from http://www.tizag.com/perlT/perluserinput.php
use 5.014;;
use warnings;


print “How old are you?”;
my $age = <>;

print “What is your favorite color?”;
my $color = <>;

say “You are $age, and your favorite color is $color.”;
It’s trivial, you should probably run it just to see what it does. Now take a look at our Expect Script.

Although you can read the comments yourself, let’s go over it anyways. ->spawn takes a list of arguments, with the first being a command, and the rest being any command line arguments, or options passed to said script. I could have easily just put the command in spawn, but I though I’d show a more dynamic example. After that you’ll notice I’ve hard coded 2 sets of params that could possibly be fed into the program. I also have created some 1 at a time iterators, this simply makes it easier to iterate them in expect. Now onto the Expect object itself.

If you’ve read the documentation you’ll notice there are 3 debug settings, with 3 being the most verbose, and some verbose settings. None of this appeared to be as verbose as I could get, however turning on ->exp_internal(1); printed everything I needed to understand expect and debug what I was doing wrong. The ->spawn method of course forks and execs our command, the output of which then gets iterated by ->expect.

The first argument to ->expect is the timeout, which is measured in seconds. The timeout is how long expect will wait for the output to match one of the regexes. You could set it to undef if you want to wait forever, or if it’s just a program that has some startup time before it prompts set it to a few seconds. The timeout will (by default) be used again in between each prompt.

After timeout you can specify a list of array refs, each of which has 2 elements. The first is a regular expression that will allow you to tell expect how to recognize a prompt. The second is a coderef which allows you to tell expect what to do if it’s corresponding match is hit. Both regexes will be run against every line, checking to see if they match.

Inside of our coderef we can use ->send to send input to the prompt. Remember send doesn’t automatically press enter, so be sure to add your newlines. exp_continue means after match continue using this ->expect call to try to match the next line.

When running the script you’ll notice the second regex never matches, but if reading the ‘internal’ output you’ll see that it is attempting to.

The last line is a call to ->before which in this case, not very intuitively prints everything that was in the pty after the last match, or more appropriately, before the program exited. You’ll also notice that it collects the thing that you sent to the last match.

That’s the basics of what I’ve discovered, I’m not sure I fully understand how it all works yet (which means my explanations might not be 100% correct), but perhaps me writing this will help someone else get started with Expect. Happy Hacking!


Share

comments powered by Disqus