Is there a way to execute a "read" command from a spawned ssh subprocess through expect? When I try the below code, read doesn't recognize end of input through "ENTER" key (it just goes to next line). I tried other "read" options (e.g. limiting number of characters, timeout, etc.) but they do not work. I know there are ways to get user input within Expect script itself but I need the input to be received through a bash command.
function foo() {
expect <<EOF
set timeout -1
spawn ssh -t $1
expect "]"
send "read x\r"
expect "]"
send "echo $x\r"
expect "]"
send "exit\r"
expect eof
EOF
}
Related
The expect script returning invalid command while I trying to create a folder after login to server via ssh
This is the below error I got
invalid command name "mkdir"
while executing
"mkdir new"
(file "./connecttotravalour.exp" line 8)
And the code on my expect script is :
#!/bin/bash
#connect to travalour host
spawn ssh travalour#travalour.local
expect "password"
send "P#ssw0rd\r"
interact
mkdir new
Posting an answer form askubuntu for similar question
The main thrust of expect programming is send and expect pairs: you send some text to the spawned process and expect a response. In this case, you send the mkdir command, and expect to see your prompt to know that the command has completed. Prompts are best matched as regular expressions to match the end of it. Since prompts are so configurable, you might want to edit the prompt expression: this one matches a literal dollar sign and a space at the end of the string.
#!/bin/bash
#connect to travalour host
spawn ssh travalour#travalour.local
expect "password"
send "P#ssw0rd\r"
set prompt_re {\$ $}
expect -re $prompt_re
send "mkdir -p new"
expect -re $prompt_re
interact
I have a shell script batch_wrapper.sh which takes user input and it invokes another script batch.sh.
These two script work perfectly fine.
Now, I have created a expect script test.sh which invokes batch_wrapper.sh and provides the input parameter.
However, for some reason, batch.sh script is not getting invoked which I spawn batch_wrapper.sh from expect script. How can I fix this?
Sample expect script is:
#!/usr/bin/expect
set timeout 2000
spawn "./batch_wrapper.sh"
expect "username" {send "Vikas\r" }
Sample Shell Scripts are:
batch_wrapper.sh
#!/bin/bash
echo "enter username"
read name
echo "your name is $name"
./batch.sh
batch.sh
#!/bin/bash
echo "Inside batch"
echo "exiting batch"
Your script exits immediately afterwards as there's nothing left to do.
You can add interact or expect eof {} as the last line in your expect script to make it process the remainding output:
$ cat lol.expect
#!/usr/bin/expect
set timeout 2000
spawn "./batch_wrapper.sh"
expect "username" {send "Vikas\r" }
expect eof {}
$ expect -f lol.expect
spawn ./batch_wrapper.sh
enter username
Vikas
your name is Vikas
Inside batch
exiting batch
I'm trying to execute commands remotely over ssh using an expect script that will log in with a password. So far I have the following script (details changed of course):
#!/usr/bin/expect
spawn ssh user1#cpu3.lab.ie
expect "password:"
send "psw123\r"
expect "$"
send "mkdir pswdtest\r"
I name this script testpswd.sh and then runchmod +x testpswd.sh, d2u testpswd.sh and ./testpswd.sh.
Apparently the script manages to login because I get the Last login:... prompt. However, after this the script seems to wait for a bit and then exit back out of ssh, without making a directory called pswdtest (as I can check afterwards).
I have tried looking up tutorials etc and changing the script above in all ways I could think of, e.g. expect "user1#cpu3:~$"instead of expect "$" and so on.
I'm running windows and use cygwin (hence the d2u), and the network I'm logging into uses Linux.
Any ideas?
While developing an expect script, always add exp_internal 1 at the top of the script: expect will show you what it's matching (or not).
Perhaps you could match the prompt with this: expect -re {\$\s*$}
After you send something, you should expect something
exp_internal 1
set prompt {\$\s*$}
spawn ssh user1#cpu3.lab.ie
expect "password:"
send "psw123\r"
expect -re $prompt
send "mkdir pswdtest\r"
expect -re $prompt
send "exit\r"
expect eof
In the below code (which will run on my linux machine), I am trying to copy run_check_node.sh to two different remote linux machine and then executing that script from my machine only.
Issue: The run_check_node.sh script takes around 25 minutes to execute. But the run_check_node.sh script execution on the remote linux machine stops after around 3-4 minutes and then next iteration of for loop is taken. Same thing happen in this next iteration also. I tried using set timeout 1200, to account for those 25 min, but still same issue. Can anyone please help what to do?
Question: The machine IPs I am using, sometimes they ask for password and sometimes don't. So, I am expecting for it. So, in case no password is asked, it simply throws some message on console and below script execution continues. Please tell if this is correct way of handling of whether password will be asked or not?
#!/bin/bash
Linux1_ip=10.20.30.40
Linux2_ip=10.100.20.30
pass="Gaur"
IP=("$Linux1_ip" "$Linux2_ip")
home="/post_checks"
############################ Linux_ip CHECKS ####################################
for ne in "${IP[#]}"
do
expect -c "
spawn ssh root#$ne \"mkdir /post_checks_$ne\"
expect yes/no { send yes\r; exp_continue }
expect password { send $pass\r; exp_continue }
exit
"
expect -c "
spawn scp $home/run_check_node.sh root#$ne:/post_checks_$ne/
expect yes/no { send yes\r; exp_continue }
expect password { send $pass\r; exp_continue }
exit
"
expect -c "
spawn ssh root#$ne \"chmod +x /post_checks_$ne/run_check_node.sh; bash /post_checks_$ne/run_check_node.sh\"
expect yes/no { send yes\r; exp_continue }
expect password { send $pass\r; exp_continue }
exit
"
fi
done
Now, this may not explain why you're seeing what you're seeing, but it may be a useful workaround.
How about you try to execute your run_check_node.sh shell script on the remote in the background? You would then disconnect and let it complete on its own.
So, basically, your 3rd spawn line would be:
spawn ssh root#$ne \"chmod +x /post_checks_$ne/run_check_node.sh; bash /post_checks_$ne/run_check_node.sh &\"
If you needed to check on completion of the shell script, what I'm proposing would not be acceptable... but I don't see your Bash script doing any checking on that, so I'm thinking it may work for you.
Try it out and let me know how it goes.
I just got some help in automating my password input during an SFTP connection by using Expect.
I then tried to issue a put command and things got complicated again. I'm using the following code:
#!/usr/bin/expect
#!/bin/sh
expect -c "
spawn sftp remoteuser#*.*.*.*
expect \"remoteuser#*.*.*.*'s password:\"
send \"passwrd\r\"
interact "
echo "put output/data.xml\r"
echo "quit\r"
My password input and connection to the remote server works just fine but I am struggling to get the put output/data.xml command to display and execute at the SFTP prompt.
My echo "put output/data.xml\r" and echo "quit\r" lines just print as text which is not entirely surprising but I really don't know what else might work.
I understand you need some help, but you should at least try doing some reading. When you say expect -c 'some stuff ...', you are specifying the entire expect script as the parameter to the -c option. The Expect session will not exist afterward.
Also, try to understand what the interact command does instead of blindly applying what someone advises.
Anyway, the solution:
expect <<'END_EXPECT'
set timeout -1
spawn sftp remoteuser#1.2.3.4
expect "[Pp]assword:"
send "passwrd\r"
expect "whatever the sftp prompt looks like"
send "put output/data.xml\r"
expect "whatever the sftp prompt looks like"
send "quit\r"
expect eof
END_EXPECT
Note that the here-doc delimiter is quoted when you first see it. That way, you will not be subjected to any shell expansions. It's like the entire here-doc is single-quoted.