http://www.perlmonks.org?node_id=1123511

amagana has asked for the wisdom of the Perl Monks concerning the following question:

The script stops and says su: incorrect password, these are Linux boxes at when it sends the passwords during the expect/send of su - root.

Is it because I will have to escape the special characters when it starts to send the strings with special characters, I did not have to do this with Solaris boxes?

Is there a way to just alway ignore special characters only during the send part of expect?

#!/usr/bin/perl -w use warnings; use strict; use Expect; my $filename = "/var/tmp/expect_script.log"; my $header = "\r\n\r\n======= system =======\r\n"; my $timeout = 60; #This will open a file and push it to array my @servers; #open (my $file, '<', $ARGV[0]) or die $!; open (my $file, '<', "/home/amagana/scripts/lists/list_b2") or die $! +; while(<$file>) { push (@servers, $_); #push each line of the file to array } print "$_\n" for(@servers); #This is an array #my @servers = qw( # # # # #); for my $server (@servers) { # do your thing with $server change_password($server); } use strict; use Expect; sub change_password { my $system = shift; my $ssh = Expect->new('ssh amagana@' . $system); my $timeout = 60; $ssh->debug(22); $ssh->log_file("$filename"); my $my_header = $header; $my_header =~ s/system/$system/; $ssh->print_log_file($my_header); [ qr/password:/], $ssh->expect ( $timeout, [ qr/password:/], [ qr/Are you sure you want to continue connecting \(yes\/n +o\)?/] ); $ssh->send("yes\r"); if ($ssh->match() =~ m/Are you sure you want to continue connect +ing \(yes\/no\)?/ ) { $ssh->send("yes\r"); } elsif ($ssh->match() =~ m/password:/ ) { $ssh->send("mycurrentpassword\n"); #no problem with the special +characters at this line } $ssh->send("su - root\n"); $ssh->expect(60, '$'); $ssh->send("su - root\n"); $ssh->expect(60, 'Password:'); $ssh->send( "rootpasswordwithspecialcharacters\n" ); #but my scr +ipt quits here $ssh->expect(60, '#'); $ssh->send("hostname\n"); $ssh->expect(60, '#'); $ssh->send("uptime\n");ana\n"); $ssh->expect(60, '#');UNIX Password:'); #linux $ssh->send("passwd amagana\n");pecialcharacters\n" ); $ssh->expect(60, 'New UNIX Password:'); #linux#linux $ssh->send( "mynewpasswordwithspecialcharacters\n" ); $ssh->expect(60, 'Retype new UNIX password:'); #linux $ssh->send( "mynewpasswordwithspecialcharacters\n" ); $ssh->expect(60, '#'); $ssh->send("exit\n"); $ssh->expect(60, '$'); $ssh->send("exit\n"); $ssh->close(); }

Replies are listed 'Best First'.
Re: How do I get expect.pm to ignore special characters?
by sn1987a (Deacon) on Apr 15, 2015 at 15:15 UTC

    Do the passwords have the same special characters on the different machines. Some "special" characters are treated differently inside double quotes. To avoid that use single quotes.

    $ssh->send( 'rootpasswordwithspecialcharacters' . "\n" );

    The single quotes are used to protect that characters in the root password. The newline is then concatenated to the end, since \n depends on being in double quotes.

      Thank you sn1987a,

      Success!, My script can now send and expect from a file and push that to an array. Thank you so very much again now I just need a little more help on how to get my script to make a list of which password resets failed from each list.

        Well you could return values:

        $ssh->expect(5, '#') or return "ERROR"

        You can also lower the amount of timeout, 60 is ok while you make the initial handshake connection, but you must have a WAN if you need to wait 60 seconds for the other prompt. Any way; and at the end of the subroutine:

        return "OK"; }

        Then in your main loop, you pick that value up:

        for my $server (@servers) { # do your thing with $server $rc = change_password($server); if($rc eq "ERROR"){ die "PANIC for $server"} }

        Modify change_password to return a status, true(1) if it succeeded or false(0) otherwise. Then check the return value in the main loop:

        my @fail_servers; for my $server (@servers) { # do your thing with $server push @failed_servers, $server unless change_password($server); }

      Hello sn1987a

      The code worked with my solaris boxes but I am having trouble with my script with my Linux boxes it stops at the screen like this example,

      Starting EXPECT pattern matching... at /usr/lib/perl5/site_perl/5.8.8/Expect.pm line 561 Expect::expect('Expect=GLOB(0x4ecd240)', 60, 'ARRAY(0x4ecd860) +', 'ARRAY(0x4ecd8c0)') called at ./linux_enc.pl li ne 56 main::change_password('remotelinuxhost\x{a}') called at ./linu +x_enc.pl line 39 I've read & consent to terms in IS user agreem't. amagana@remotelinuxhost's password: Starting EXPECT pattern matching.. +. at /usr/lib/perl5/site_perl/5.8.8/Expect.pm line 561 Expect::expect('Expect=GLOB(0x4ecd240)', 60, '$') called at ./ +linux_enc.pl line 73 main::change_password('remotelinuxhost\x{a}') called at ./linu +x_enc.pl line 39 Permission denied, please try again. amagana@remotelinuxhost's password:

      After that I went to the target box and cleared out the pam_tally2 and then my perl script worked.

        After that I went to the target box and cleared out the pam_tally2 and then my perl script worked.

        If I understood you correctly and the script is now working, then the account got locked while you where debugging your script or was locked for some other failed log in attempts. Is there something that is not working if you run your script now?