Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

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
[erix]: or compile & run an instance as yourself (not user 'postgres')
[erix]: easiest setup is to run with PG* env variables set, and a custom .pgpass files (can be a $PGPASSFILE)
[Corion]: Hmm - "trust" sounds interesting, but I have still to find whether I can restrict that on a per-DB level ;)
[Corion]: erix: Sure, but SQLite doesn't even need that :)
[hippo]: Corion: Yes, you can. It's all in the pg_hba.conf
[erix]: yeah, but there is a lot SQLite cannot do :)
[hippo]: Database is the 2nd column.
shmem .oO( docker. docker. docker? docker. docker! docker )
[shmem]: at least, some Ook.
[erix]: another simple Pg thing is to running a database off a tsv (alas, readonly)

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (14)
As of 2018-02-23 15:14 GMT
Find Nodes?
    Voting Booth?
    When it is dark outside I am happiest to see ...

    Results (302 votes). Check out past polls.