Skip to content

Instantly share code, notes, and snippets.

@tommybutler
Last active December 25, 2015 06:49
Show Gist options
  • Save tommybutler/6934497 to your computer and use it in GitHub Desktop.
Save tommybutler/6934497 to your computer and use it in GitHub Desktop.
Example using Perl expect to automate a shell login (Linux bash). The individual subs could/shoud be wrapped with Moose (around => subname)
#!/usr/bin/env perl
use Modern::Perl;
use 5.016;
use Expect;
use File::Util;
use Time::HiRes qw( time );
my $log = File::Util->new->open_handle( '/tmp/expectlog' => 'append' );
$|++; # no bufferin'
my $exp = Expect->new();
$exp->log_file( '/tmp/expecthist' );
$exp->log_stdout( 0 );
$exp->raw_pty( 1 );
$exp->spawn( '/bin/bash' ) or die qq{Can't start a shell!};
$exp->slave->stty( '-echo' ); # << install IO::Stty (latest) for this!
$exp->send( "ls -l ./\n" );
$exp->expect( 3 =>
[ qr/test_expect/sm => \&found_myself ],
[ qr/uid.*\(tommy/sm => \&found_tommy ],
[ qr/jesse.*tommy/ => \&found_jesse ],
[ qr/password:/i => \&got_passwd ],
[ qr/jesse@.*?\$\s+$/ => \&got_prompt ],
[ qr/uid.*\(jesse/ => \&login_worked ],
[ timeout => \&timed_out ],
[ eof => \&got_eof ],
-re => qr/^\$\s+$/sm,
);
sleep 3;
$exp->hard_close();
say $log time, 'DONE!';
close $log;
exit;
# --- SUBROUTINES ---------------------
sub got_eof
{
my $exp = shift;
$exp->clear_accum();
say 'GOT EOF!';
}
sub found_myself
{
my $exp = shift;
$exp->clear_accum();
say $log time, 'PERL FOUND!!!!!!!!!';
$exp->send( "id\n" );
exp_continue;
}
sub found_tommy
{
my $exp = shift;
$exp->clear_accum();
say $log time, 'TOMMY FOUND IN `id`';
$exp->send( "ls /home\n" );
exp_continue;
}
sub found_jesse
{
my $exp = shift;
$exp->clear_accum();
say $log time, 'JESSE FOUND';
$exp->send( "su - jesse\n" );
exp_continue;
}
sub got_passwd
{
my $exp = shift;
$exp->clear_accum();
say $log time, 'GOT PASSWORD PROMPT';
$exp->send( "*******\n" ); # password not shown (we aren't using passwords anyway)
exp_continue;
}
sub got_prompt
{
my $exp = shift;
$exp->clear_accum();
say $log time, 'PASSWORD SENT. CHECKING IF IT WORKED';
$exp->send( "id\n" );
exp_continue;
}
sub login_worked
{
my $exp = shift;
$exp->clear_accum();
say $log time, 'LOGIN WORKED! I AM LOGGED IN AS JESSE!';
$exp->send( "touch iwashere ; exit\n" );
}
sub timed_out
{
my $fail = qq(TIMEOUT! Not what we EXPECT-ed);
say $log time, $fail;
die $fail;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment