BioRod
BioRod

Reputation: 549

Expect script ends without error at the New Password prompt

I have Solaris servers of which I'm not sure if I changed the password to a particular account. Either I'm going to authenticate successfully because I already changed the password or I'm going to authenticate with the old password and it will prompt me to change my password after I authenticate with the old password because it expired.

Warning: Your password has expired, please change it now.
New Password: 

The script will stop at the New Password: prompt and exits w/o an error.

#!/bin/bash

NewPassword="cccccc"
OtherPassword="ffffffff"

for i in `cat x.txt`

do

/opt/csw/bin/expect -f  <(cat << EOF

spawn ssh -o StrictHostKeyChecking=no adminuser@$i
expect "Password: "
send "$NewPassword\r"

expect {
"$ " { 
## new password worked 
     send "uname -a\r"
}
"Password: " {
 ## The new password did not work 
    send "$OtherPassword\r"
    expect "$ "
}
"New Password: " {
 ## after authenticating, my old password expired need to change it now
    send ${NewPassword}\r
    expect "Re-enter new Password: "
    send ${NewPassword}\r
    expect "$ "
}
}
EOF
)
done

Upvotes: 1

Views: 116

Answers (2)

glenn jackman
glenn jackman

Reputation: 246744

In addition to Donal's cogent advice, a couple of notes:

  1. In the shell part, don't read lines with for
  2. using a process substitution and cat and a here document is overkill: you just need the here-doc
  3. use exp_continue to handle the exceptional cases that occur before you see the prompt
  4. exit your login session and expect to see it close so you don't have to wait around to timeout.
#!/bin/bash
NewPassword="cccccc"
OtherPassword="ffffffff"

while read server; do
    /opt/csw/bin/expect << EOF
        spawn ssh -o StrictHostKeyChecking=no adminuser@$server
        expect "Password: "
        send "$NewPassword\r"
        set count 0
        expect {
            "New Password: " {
                ## after authenticating, my old password expired need to change it now
                send ${NewPassword}\r
                expect "Re-enter new Password: "
                send ${NewPassword}\r
                exp_continue
            }
            "Password: " {
                if {[incr count] == 2} {
                    error "neither new password nor old password worked for $server"
                }
                ## The new password did not work 
                send "$OtherPassword\r"
                exp_continue
            }
            "$ "
        }
        send "uname -a\r"
        expect "$ "
        send "exit\r"
        expect eof
EOF
done < x.txt

Upvotes: 1

Donal Fellows
Donal Fellows

Reputation: 137557

The order of clauses in the expect matters; the internal matcher tries the different matching rules in the order you specify. This is important here because the rule for Password: also matches what New Password: will match, and so will have priority over it.

Swap the two clauses or rewrite them so that they can't both match the same input text (probably by including the newline or changing to using anchored regular expressions). Swapping them is far easier.

Upvotes: 2

Related Questions