Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

regular expression matching in expect

by cmastays (Initiate)
on Aug 06, 2012 at 17:57 UTC ( #985785=perlquestion: print w/replies, xml ) Need Help??
cmastays has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks I am writing a perl script using to ssh into a system and run a whole bunch of linux commands to automatically install our application. I want to execute next step only if the previous step returns the appropriate match for the shell prompt I am stuck with a regular expression match for the shell prompt- This is what i have so far. and I am stuck at the last step since it is not matching it. Am i taking the right approach and also can u please let me know what i have goofed up here to match root@ ~#
$exp->expect($timeout, [ qr'login: $', sub { $spawn_ok = 1; my $fh = shift; $fh->send("$sshUsername\n"); exp_continue; } ], [ 'password: $', sub { my $fh = shift; print $fh "$sshPWD\n"; exp_continue; } ], # I need your help here [ qr'/[root@]$/' => sub { my $fh = shift; print " +regular exp matched \n"; $fh->send("cd /u0x/tmp\n"); exp_continue; } ] );

Replies are listed 'Best First'.
Re: regular expression matching in expect
by aitap (Curate) on Aug 06, 2012 at 18:30 UTC
    to match root@ ~#
    Did you mean [root@hostname ~]#? Here is the regular expression to match it: qr/^\[root@\w*\s*~\]#/ (assuming that there can be a hostname after "@" and some kind of space character between the hostname and current directory).
    Sorry if my advice was wrong.
      That regular expression works fine. Thanks a lot.

      However i am facing a new issue now. After ssh, I can encounter either RSA key authentication and password prompt(First time) or only password prompt. Then I want to be able to continue to look for bash prompt so that I can continue my other linux commands.Here is my code snippet

      $exp->spawn("ssh -l root $sshHostname") or die "cannot spawn ssh: $!\n +"; $exp->expect($timeout,[ qr/RSA/i,#/ sub { my $fh = shift; $fh->send("yes\n"); }); $exp->expect($timeout,'-re','password' => sub { my $fh = shift; $fh->send("$sshPWD\n");} ); $exp->log_file->print("#Successfully ssh'ed in\n"); $exp->expect($timeout, '-re','~]#' => sub {my $fh = shift; $fh->send("cd /u0x/tmp\n");}
        If you're not too picky about remote host authentication...
        ssh -o 'StrictHostKeyChecking no' -o 'CheckHostIP no' $host
        See man ssh_config for more details. It can also be handy to use options to set the known_hosts file to /dev/null. Otherwise if you're picky it's probably best to manually ssh to all of your destination hosts once and accept the key manually and then failing if you get anything but login / password. It may be even handier to use the -l option to ssh to specify the login name so you don't have to try and match for the login case. Then you get down to the way my simple scripts of this type work: ssh as a specific user, ignore host key stuff, just wait for password and then the prompt... anything else is a die.
        Well, what error message do you receive? According to the documentation, near the New more Tcl/Expect-like interface of $object->expect(), you can return 'exp_continue' symbol from your callback sub to continue matching with next callback.
        Are you sure it won't be easier to use some SSH-related modules, for example, Net::SSH::Expect?
        Sorry if my advice was wrong.
Re: regular expression matching in expect
by hbm (Hermit) on Aug 10, 2012 at 00:45 UTC
    Am i taking the right approach

    Having done a lot of this, I would:

    1. Set up an ssh-key, to log in automatically without Expect - as a non-root user.
    2. Write one Expect script for each of the (few?) commands that are interactive.
    3. Write one straightforward wrapper to tie it all together.
    4. Enable the non-root user to run the wrapper with sudo.

    Something like this:

    ssh admin@host "sudo /path/to/"

    Where the wrapper might:

    ... die("...") if system("/path/to/")!=0; die("...") if system("/path/to/")!=0; ...

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://985785]
Approved by lidden
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (9)
As of 2018-06-20 21:36 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (117 votes). Check out past polls.