Expect Script - enter password then run bash script - bash

I have a bash script that calls an expect script with a password that initiates the ssh process:
#!/usr/bin/bash
/usr/bin/expect $PWD/sshScript.exp $SSHPASSWORD
The expect script calls the ssh command, waits for prompt to enter password and sends in the password.
#!/usr/bin/expect
set password [lindex $argv 0];
spawn ssh -o "StrictHostKeyChecking no" username#host
expect "Enter your AD Password:" {
send "$password\r"
}
I can get the remote server to ssh correctly and display the [user#host ~]$ but I want to add to the expect script a way to automatically run a bash script that is stored in the same location as the other two scripts.
I've tried to
a) scp the file to the remote and call it in the server but I can't seem to get expect to send any text pass the password
b) do spawn ssh -o "StrictHostKeyChecking no" username#host < secondscript.shto send in the script to run but it won't wait for the password to be entered before trying to run the script.

You may combine you bash and expect script together and use it to copy the 3rd bash script to the remote server, execute it and return the output.
Here's a simple NON-TESTED example:
#!/bin/bash
[... other bash code here ...]
SCRIPT='/path/to/script/to/run/remotely.sh'
LOGIN='test'
IP='your ip or hostname'
LOCATION='/destination/path/to/script/to/run/remotely.sh'
### start expect part here, you may add '-d' after 'expect' for debug
/usr/bin/expect << EOD
### set a 3 minute timeout
set timeout 180
### copy the script you wish to run on the remote machine
spawn scp -o StrictHostKeyChecking=no -p $SCRIPT $LOGIN#$IP:$LOCATION
expect {
timeout { send_user "\n# TIMED OUT. HOST NOT REACHABLE #\n"; exit 3 }
"*assword: "
}
send "your_password\r"
expect {
"*assword: " { send_user "\n# Incorrect Password. Login Failed. #\n"; exit 4 }
"100%" { send_user "\nFile copied\n" }
}
### ssh to remote server to run script
spawn ssh $LOGIN#$IP
expect {
timeout { send_user "\n# TIMED OUT. SSH DAEMON or PORT 22 CLOSED #\n"; exit 6 }
"*assword: "
}
send "your_password\r"
expect {
timeout { send_user "\n# TIMED OUT. PROMPT NOT RECOGNISED! #\n"; exit 7 }
### expect the prompt symbol
-re {[#>$] }
## execute your script on the remote machine
send "$LOCATION\r"
expect {
"enter what you expect here" { send_user "\nRESULT: Message based on what you set the expect to read $IP\n" }
-re {[#>$] }
}
[... other expect code here ... ]
### exit remote ssh session
send "exit\r"
### end of expect part of script
EOD
### continue bash script here
[... other bash code here ...]

Related

Expect: How to handle spawn id exp4 not open error

My expect script:
foreach host $hostlist {
puts $host
set timeout 3
spawn ssh -t -q -o StrictHostKeychecking=no "$user\#$host"
expect {
-re "closed by remote host" { exp_continue }
-re "RSA key fingerprint" { send "yes\r"; exp_continue }
-re "(P|p)assword: " { send "$pass\r"; exp_continue }
-re $prompt { send "$cmd\r" }
eof
}
...
is throwing this error and exits right away.
spawn ssh -t -q -o StrictHostKeychecking=no myuserid#example.net
**expect: spawn id exp4 not open**
while executing
"expect -re $prompt"
("foreach" body line 12)
invoked from within
"foreach host $hostlist {
puts $host
set timeout 3
spawn ssh -t -q -o StrictHostKeychecking=no "$user\#$host"
expect {
-re "closed by rem..."
(file "./a" line 36)
whenever the ssh login attempt encounters some problem on a host like:
kex_exchange_identification: Connection closed by remote host
I tried to put various "expect" regexps but couldn't make it continue to the next host but it abruptly exits.
Anyone know of a trick on how to make it not exit but move onto the next host?
If it's not possible using tcl/expect, would it be possible using the expect module with Python or Perl?
Thank you for your help in advance!
Change
-re "closed by remote host" { exp_continue }
to
-re "closed by remote host" { continue }
You want to go to the next foreach iteration, not loop within this expect command to look for the next pattern.

Interact not working from within Expect Script

I have the following expect script within a bash script and I'm unsure as to why the interact command is not working.
expect <<-EOS
#!/usr/bin/expect
set timeout $EXP_TIMEOUT
send_user "\n The timeout being used is $EXP_TIMEOUT \n"
send_user "\nLogging into remote host via SSH:\n"
spawn ssh -q -o ConnectTimeout=$SSH_TIMEOUT -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${hostname}
expect "*assword*"
send -- "$secret\r"
expect {
"*assword*" {
send \x03
puts "\nIncorrect Password\n"
}
"$prompt" {
send -- "/usr/seos/bin/sesu - $user\r"
expect "*assword*"
send -- "$secret\r"
expect "$prompt"
send -- "id\r"
expect "$prompt"
send -- "hostname -s\r"
interact
}
}
expect eof
EOS
Thank you all for your help!
interact can't let the user enter data via stdin because you are already redirecting stdin for the here document.
Instead, you can save your here document with all expansions to a variable, and then pass that to -c. Here's a simplified example:
script=$(cat << EOF
spawn vi
send "iHello $(hostname)"
interact
EOF
)
expect -c "$script"

Expect script not prompting for sftp

i wonder what may be wrong here
I do an sftp expect script which will prompt me for password, but never seems to send the password in. Or if it does send it encrypted, we still do not get to the sftp prompt. Any ideas?
cd /proj/eiffel004_config_fem107/slaves/RHEL6.4_GE_3/workspace/Remote_Agent_Test/
/usr/bin/expect << 'EOF'
set timeout -1
spawn sftp root#server
expect {
"*assword: "
}
send "thePassword \r"
expect {
"sftp> "
}
send "put filename \r"
expect {
"100"
}
send "exit \r"
EOF
Output is
+ cd /proj/eiffel004_config_fem107/slaves/RHEL6.4_GE_3/workspace/Remote_Agent_Test/
+ /usr/bin/expect
spawn sftp root#server
Connecting to server...
Warning: Permanently added 'server,102.44.79.32' (RSA) to the list of known
hosts.
root#server's password:

User input for Expect script

I am new to scripting. How can I write an Expect script to ssh into a device and prompt the user for password? We use a pin + RSA token code as the password so I can't store the password.
#!/usr/bin/expect -f
spawn ssh device1
You will need to use the interact command to type in the password yourself.
The below skeleton should get you on your way:
set prompt "$"
spawn ssh user#host
set timeout 10
expect {
timeout {
puts "Unable to connect"
exit 1
}
#Authenticty Check
"*(yes/no)?" {
send "yes\r"
exp_continue
}
"assword: " {
#Hand control back to user
interact -o "\r" exp_continue
}
"$prompt" {
puts "Cool by the pool"
}
}
I have used this code before to achieve what you wish to achieve. You can take it as a reference point to write your own version of the code.
#!/usr/bin/env expect -f
set passw [lindex $argv 0]
#timeout is a predefined variable in expect which by default is set to 10 sec
set timeout 60
spawn ssh $user#machine
while {1} {
expect {
eof {break}
"The authenticity of host" {send "yes\r"}
"password:" {send "$password\r"}
"*\]" {send "exit\r"}
}
}
wait
#spawn_id is another default variable in expect.
#It is good practice to close spawn_id handle created by spawn command
close $spawn_id
Source: Expect Wiki
The below code will ask the user to enter the password and will use it further in the script where a password will be asked. Just as $pass.
Grabbing password to be used in script further
stty -echo
send_user -- "Enter the password: "
expect_user -re "(.*)\n"
send_user "\n"
stty echo
set pass $expect_out(1,string)

Why does Expect dump commands without execution?

I'm learning Expect, and I've noticed that my Expect scripts sometimes reach a point where they begin to dump commands without executing them. What causes this to happen? I've scraped Google and a couple Expect tutorials, but the keywords related to this issue are not filtering an answer. Any guidance or references are greatly appreciated.
Example Expect Script:
#!/usr/bin/env expect
set ip [lindex $argv 0]
spawn ssh root#$ip /dir/run.sh
expect {
"password:" {
send "secret_password\n"
}
"No route to host" {
spawn echo "This gets dumped, not executed."
}
}
Output:
$ ./ex.exp 192.168.0.22
spawn ssh root#192.168.0.22 /dir/run.sh
ssh: connect to host 192.168.0.22 port 22: No route to host
spawn echo This gets dumped, not executed.
Echo is not a command, so maybe it displays instead since it doesn't tell it to do anything.
Try this instead:
#!/usr/bin/env expect
set ip [lindex $argv 0]
spawn ssh root#$ip /dir/run.sh
expect {
"password:" {
send "secret_password\n"
}
"No route to host" {
puts stdout "Host not reachable."
}
"Connection refused" {
puts stdout "Host not accepting ssh."
}
}

Resources