Is it possible to set exit code of 'expect' - linux

The following bash script doesn't work because command 'expect' always return 0 regardless which exit code of the remote script /tmp/my.sh returns.
any idea to make it work? thanks.
#!/usr/bash
user=root
passwd=123456abcd
host=10.58.33.21
expect -c "
spawn ssh -o StrictHostKeyChecking=no -l $user $host bash -x /tmp/my.sh
expect {
\"assword:\" {send \"$passwd\r\"}
eof {exit $?}
}
"
case "$?" in
0) echo "Password successfully changed on $host by $user" ;;
1) echo "Failure, password unchanged" ;;
2) echo "Failure, new and old passwords are too similar" ;;
3) echo "Failure, password must be longer" ;;
*) echo "Password failed to change on $host" ;;
esac
Edited at 10:23 AM 11/27/2013
Thanks for the comments. Let me emphasis the problem once again,
The main script is supposed to run on linux server A silently, during which it invokes another script my.sh on server B unattended. The question is how to get exit code of my.sh?
That's why I cannot leverage ssl_key approach in my case, which requires at least one time configuration.

#!/usr/bin/expect
set user root
set passwd 123456abcd
set host 10.58.33.21
set result_code 255
# exp_internal 1 to see internal processing
exp_internal 0
spawn ssh -o StrictHostKeyChecking=no -l $user $host bash -x /tmp/my.sh && echo aaa0bbb || echo aaa$?bbb
expect {
"assword:" {send "$passwd\r"; exp_continue}
-re "aaa(.*)bbb" {set result_code $expect_out(1,string)}
eof {}
timeout {set result_code -1}
}
switch $result_code {
0 { puts "Password successfully changed on $host by $user" }
1 { puts "Failure, password unchanged" }
2 { puts "Failure, new and old passwords are too similar" }
3 { puts "Failure, password must be longer" }
-1 { puts "Failure, timeout" }
default { puts "Password failed to change on $host" }
}
exit $result_code

Related

How to automate ctrl+d action in the ssh expect script in bash?

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"

Unable to access local variable via a function call through ssh

This the code I,m trying to execute:
#!/bin/bash
set -e -a
err_report() {
echo "Error on line $1"
}
trap 'err_report $LINENO' ERR
IFS=$'\n'
value=($(cat builds.txt))
prevBuild=${value[0]}
prevBuildDir=$prevBuild
currentBuild=${value[1]}
currentBuildDir=$currentBuild
splitPrevBuild=(${prevBuild//./$'\n'})
splitcurrentBuild=(${currentBuild//./$'\n'})
prevBuildSR=${splitPrevBuild[2]}
prevBuildHF=${splitPrevBuild[3]}
prevBuildNum=${splitPrevBuild[4]}
currentBuildSR=${splitcurrentBuild[2]}
currentBuildHF=${splitcurrentBuild[3]}
currentBuildNum=${splitcurrentBuild[4]}
function change {
cd ~/InstallationFiles/${currentBuildSR}/${currentBuildDir}/${currentBuild}extracted
}
change
pwd
ssh -T atao52#kvs-in-hsglap17.in.kronos.com <<-EOF
$(typeset -f)
change
pwd
echo hi
exit
EOF
How to access the variables as currently, it says
cd: /home/atao52/InstallationFiles///extracted: No such file or directory

Blocked when i run this shell script

#!/bin/bash
SERVERS="master slave1 slave2 slave3"
for SERVER in $SERVERS
do
expect -c "set timeout -1;
spawn ssh hadoop#$SERVER;
expect {
*(yes/no)* {send -- yes\r;exp_continue}
*assword:* {send -- hadoop\r;exp_continue}
*$* {send -- \"echo 'ssss'\r\";exp_continue}
*$* {send -- exit\r;exp_continue}
eof {exit;0}
}";
done
when i run this script,it's will be block and killed.
‘SERVER’ is hostname list;
Please help me see why,what's wrong with my code.
ERROR MESSAGE AS BELOW:
spawn ssh hadoop#master
./gather_pub_key.sh: line 5: 2695 killed expect -c "set timeout -1;
spawn ssh hadoop#$SERVER;
expect {
*(yes/no)* {send -- yes\r;exp_continue}
*assword:* {send -- hadoop\r;exp_continue}
*$* {send -- \"echo 'ssss'\r\";exp_continue}
*$* {send -- exit\r;exp_continue}
eof {exit;0}
}"

Execute sudo using expect inside ssh from bash

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

Transfer environment variables with expect

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.

Resources