I have Linux red-hat machine - version 5.X
I want to create expect script that verify if ssh login to remote machine is successfully
my test is only to get the password prompt on remote login ( I not want to enter password )
its like to test ssh connectivity
what I created until now is the following script
so if I get password prompt then script need to return 0
if not then script need to return 1
the problem with my script is that - the script return 0 even ssh login is failed ( no password prompt )
#!/usr/bin/expect
set LOGIN [lindex $argv 0]
set PASSWORD [lindex $argv 1]
set IP [lindex $argv 2]
set timeout 10
spawn ssh -o StrictHostKeyChecking=no $LOGIN#$IP
expect -re "(Password:|word:)"
exit 0
expect {
timeout {error "incorrect password"; exit 1}
eof
}
please advice how to update my script ?
You have to enclose the condition in one expect as,
set timeout 10
spawn ssh -o StrictHostKeyChecking=no $LOGIN#$IP
expect {
timeout {puts "Timeout happened";exit 0}
eof {puts "EOF received"; exit 0}
-nocase "password:" {puts "SSH connection is alive for the host $IP"; exit 1}
}
Have a look at the here which resembles your question.
sshlogin.expect :
set timeout 60
spawn ssh [lindex $argv 1]#[lindex $argv 0]
expect "yes/no" {
send "yes\r"
expect "*?assword" { send "[lindex $argv 2]\r" }
} "*?assword" { send "[lindex $argv 2]\r" }
interact
Usage :
sshlogin.expect <host> <ssh user> <ssh password>
Related
I have a usecase where I need to execute a command after connecting to the host through ssh. After the command execution, I need to perform Ctrl-D and Ctrl-M so that I can issue other commands.
I tried with using EOF but It is completely closing the session.
expect << EOF
spawn ssh -o StrictHostKeyChecking=no LocalCOMUser#$nodeIp -p $ssh_port
expect {
"password:" {}
timeout { send_user "Timed out in ssh connection" ;exit 1}
}
send "p#ssword\r"
expect {
">" {}
timeout { send_user "Timed out in ssh connection" ;exit 1}
}
set timeout 120
send "mml\r"
expect {
"<" {}
timeout { send_user "Timed out in ssh connection" ;exit 1}
}
send "$command1\r"
expect {
"<" {}
}
send "exit;\r"
expect {
">" {}
timeout { send_user "Timed out in ssh connection" ;exit 1}
}
send "exit\r"
EOF
Need a command that does action as Ctrl-d.
You can simulate pressing Ctrl-D by sending the ^D/␄ character:
send "\x04"
I want to create a script that automates a installation on multiple linux hosts.
I login to the hosts using ssh keys and inside the login I want to do a sudo, I am trying to use expect, which I have on the stations but I don't have on the server which runs the script.
How do I do this, this is my try, but no luck with it:
#!/bin/bash
ssh user#station04 <<EOF
expect -d -c "
send \"sudo ls\"
expect {
\"password:\" { send '1234'; exp_continue }
\"$user#\"{
send "exit\r"
}
default {exit 1}
}"
EOF
exit
The result:
send: sending "sudo ls" to { exp0 }
expect: does "" (spawn_id exp0) match glob pattern "password:"? no
expect: read eof
expect: set expect_out(spawn_id) "exp0"
expect: set expect_out(buffer) ""
argv[0] = expect argv[1] = -d argv[2] = -c argv[3] =
send "sudo ls\r"
expect {
"password:" { send '1234'; exp_continue }
"#"{
send exitr
}
default {exit 1}
}
set argc 0
set argv0 "expect"
set argv ""
A.K
What about this? <- just make sure of the expected prompts.
#!/bin/bash
expect <<'END'
spawn ssh user#station04
expect "password:"
send "$pw\r"
expect "#"
send "sudo ls\r"
END
I suggest you would use public key authentication for the ssh part, then just use something like:
ssh -t username#server-ip -C "echo sudo-password | /usr/bin/sudo -S ls"
You got the usage of expect not quite right - don't send a command; rather spawn the command and send just its input. So, your script becomes:
ssh … <<EOF
expect -d -c "
spawn sudo ls
expect -nocase password: { send 1234\r }
expect eof
"
exit
EOF
So I am having trouble making TestCases with expect scripts, I have like 10 TestCases which all starts and ends with the same "functions" like login and logout or turning some flags off, is there a possibility to include them or execute them remotely from my script, like spawn login.exp or even better to put them in functions ?
TC01.exp
#!/usr/bin/expect -f
set timeout 5
#example of getting arguments passed from command line..
#not necessarily the best practice for passwords though...
set server [lindex $argv 0]
set user [lindex $argv 1]
set pass [lindex $argv 2]
set no [lindex $argv 3]
set counter 0
# connect to server via ssh, login, and su to root
send_user "connecting to $server\n"
spawn ssh $user#$server
#login handles cases:
# login with keys (no user/pass)
# user/pass
# login with keys (first time verification)
expect {
"> " { }
"$ " { }
"assword: " {
send "$pass\n"
expect {
"> " { }
"$ " { }
"assword: " {
send_user "\nLogin failed\n"
incr counter 1
exit 5
}
}
}
"(yes/no)? " {
send "yes\n"
expect {
"> " { }
"$ " { }
}
}
default {
send_user "Login failed\n"
incr counter 1
exit
}
}
#TEST CASE HERE
#login out
send "exit\n"
expect {
"> " {}
default {}
}
if { $counter > 0 } {
send_user "\nTestCase finished with some errors!\nFAILED!!!\nERRORS $counter\n";
exit 4;
}
send_user "\nTestCase finished with SUCCESS!\nERRORS: $counter\n";
So i would like to have login and count_error as functions, so I would be able to create my test cases just like this:
TC01.exp
#!/usr/bin/expect -f
set timeout 5
set server [lindex $argv 0]
set user [lindex $argv 1]
set pass [lindex $argv 2]
set no [lindex $argv 3]
set counter 0
login($server, $user, $pass)
#TestCase
Errors($counter)
exit
Expect is actually Tcl with some bindings to pty's and fork() thrown in. All very well described on http://tcl.tk
Functions in Tcl are done with proc (look here) eg:
lib.tcl
proc login {server user pass} {
# Your expect code goes here
return $errorCount
}
proc errors {errorCount} {
if {$errorCount > 0} {
# Your error handling code here
}
}
test:
#!/usr/bin/env expect
source lib.tcl
set errors [login $server $user $pass]
# your test case here
errors $errors
I ran into the problem that it keeps exit and I just couldn't figure it out why it couldn't put in anymore expect any send statement to keep the SSH session going???
#!/usr/bin/expect
set timeout 15
set hostname [lindex $argv 0]
set username [lindex $argv 1]
set password [lindex $argv 2]
set enable [lindex $argv 3]
set send_slow {10 .001}
log_user 1
expect -f snmp2.exp 172.28.135.24 localadmin Gr0upM540 z540Mxy3
set configuration /tmp/ntp
set routerlist [open "/tmp/routerlist" "r"]
set logfile [open "/tmp/ntp_config" "w"]
spawn ssh $username#$hostname
expect {
timeout { send_user "\nFailed to get password prompt\n"; exit 1 }
eof { send_user "\nSSH failure for $hostname\n"; exit 1 }
"*#" {}
"*assword:" {
send "$password\r"
}
}
send "/r"
expect {
"*#" {}
"*>" {
send "enable\r"
expect "*assword"
send "$enable\r"
expect "*#"
}
}
send "exit\r"
send_user "\nSuccessfully changed SNMP password on $hostname\n"
close
I am writing an expect script and need to transfer environment variables over a telnet session (which the man page proudly touts as a feature but provides no other mention).
So something like this:
#!/usr/bin/expect -c
spawn telnet 1.2.3.4
set rpath ""
expect "#" { set rpath $PATH }
where $PATH is in the environment of the remote system..any ideas?
You could easily do this by spawning bash and then issue telnet to the remote system.
I presume you want to set the path variable from the local machine to the remote machine.
#!/bin/sh
# the next line restarts using tclsh \
exec expect "$0" "$#"
set prompt "~$"
set hostname "anyhost"
spawn bash
send "echo $PATH\r"
expect {
$prompt {
set pathVariable $expect_out(buffer)
}
timeout {
send_user "path hasn't been set - exiting\n"
close
exit 1
}
}
send "telnet $hostname\r"
expect {
"Login:" {}
"telnet: " {
send_error "$argv0 couldn't login to $hostname\n"
exit 1;
}
timeout {
send_error "$argv0 couldn't login to $hostname, timeout of $timeout passed\n"
exit 1;
}
}
send "$username\r"
expect "Password:"
send "$password\r"
expect $remotePrompt
send "bash\r"
send "export PATH=$pathVariable\r"
# continue with whatever you want.