Reputation: 1609
This piece of code works fine without command line parameters but stops after login into the linux box when i am passing the IP as a parameter to the script
bash -x -o igncr Master.sh 10.104.24.196
I am clueless what is going on, any help will be appreciated.
if [ "$#" -eq 0 ]; then
IP="10.104.24.196"
else
IP="$1"
fi
PWD="something"
echo "Connecting to $IP with password:$PWD"
> ~/.ssh/known_hosts
/usr/bin/expect -<< EOD
set timeout -1
spawn ssh "$IP" -l root
expect "(yes/no)?"
send "yes\n"
expect "password"
send "$PWD\n"
expect "$*" <- stops here
send "cd somewhere\n"
send "./db_deploy.sh\n"
expect "Script execution completed."
send "cd somewhere\n"
send "./apps_deploy.sh\n"
expect "Script execution completed."
send "exit\n"
expect eof
EOD
#dosomething else
Upvotes: 1
Views: 680
Reputation: 16436
The problem is because of expect "$*"
.
If you want to match the literal dollar sign ($
), then you should use the following way when used inside double quotes.
expect {\\\$}
Since $
sign is special to both tcl
and expect
, in order to match the literal dollar sign, we need to escape it with backslash twice and of course one more backslash to escape the backslash itself.
There are 2 more enhancements which can be done are as follows,
To send 'enter/return' key via expect
, we are advised to use \r
, not \n
. (Though it is not big deal in your question. :))
Before spawning ssh session , you are overwriting the known_hosts
file (> ~/.ssh/known_hosts
) and thereby you are expecting for '(yes/no)' which happen only when the host is new to the system.
spawn ssh "$IP" -l root
expect "(yes/no)?
With the help of exp_continue
, we can handle the same without overwriting the known_hosts. (But, if deleting the known hosts each time is your real intention, you do not need to add this part)
By combining these changes in your script, it will be like as follows,
#!/bin/bash
if [ "$#" -eq 0 ]; then
IP="10.104.24.196"
else
IP="$1"
fi
PWD="something"
echo "Connecting to $IP with password:$PWD"
# I have commented this line, since I am using exp_continue.
# If you don't want, then keep your code as such
#> ~/.ssh/known_hosts
/usr/bin/expect -<< EOD
set timeout 60; # 1 min of timeout
spawn ssh "$IP" -l root
expect {
# you can keep your old code here if you want.
"(yes/no)" {send "yes\r";exp_continue}
"password"
}
send "$PWD\r"
expect {\\\$}
send "cd somewhere\r"
send "./db_deploy.sh\r"
expect "Script execution completed."
send "cd somewhere\r"
send "./apps_deploy.sh\r"
expect "Script execution completed."
send "exit\r"
expect eof
EOD
Instead of embedding expect script directly into the bash script, you can keep the file separately and call the expect script like as follows,
expect -c yourscript.exp
Have a look at here to know about usage of double quotes and single quotes while embedding the expect script in a bash script.
Update : How poor I'm to miss the timeout
value.
expect
's default timeout value is 10 seconds. This can be changed by setting a new value.
set timeout 60; # This value is in terms of seconds.
By setting timeout to -1, we are making it to wait for infinitely. You have used that value. Try changing that to some other value (like 60 which is 1 min).
Perhaps, in your case, if $
didn't get matched, it will proceed as such. If you want to handle the timeout
gracefully, you should have use the following.
expect {
{\\\$} {puts "matched dollar sign"}
timeout { puts "timeout happened"}
}
Still this does not answer your question precisely. Can you try the expect
with -d
flag and share the output in your question ? So that we can help you.
Upvotes: 2