I need a script to configure PDU (power distribution unit). The script will be called from another program. I created Expect script that gets parameters, connects to PDU by ssh and runs the command. The short commands, such as 'pwd' or 'lang' works correctly, but the long commands stuck waiting for user interaction. If I do nothing, the connection is closed after timeout, if I press Enter, the script continue and pass.
There is a script:
spawn ssh $user#$pdu
interact -o -nobuffer "assword:" return
send "$password\r"
interact -o -nobuffer "apc>" return
send "olStatus $host\r"
interact -o -nobuffer "apc>" return
Running it with debug flag gave the following output
apc>tty_set: raw = 0, echo = 1
send: sending "olStatus machine-123456\r" to { exp4 }
defining key apc>, action return
tty_raw_noecho: was raw = 0 echo = 1
spawn id exp4 sent <olStatus machine-123>
olStatus machine-123spawn id exp0 sent <\r>
spawn id exp4 sent <456\r\n23: machine-123456: On \r\nE000: Success\r\n\r\napc>\r\napc>>
456
23: machine-123456: On
E000: Success
Here I added the comments
How can I solve the problem?
This is what I'd suggest:
spawn ssh $user#$pdu
expect "assword:"
send "$password\r"
expect -re {apc>$}
send "olStatus $host\r"
expect -re {apc>$}
send "exit\r" # or "quit" or whatever
expect eof
But run it with debug enabled and let me know what you get.
Thanks to #GlennJackman
I ran autoexpect and this help me to understand how to solve the issue. Maybe it is a my system problem, but currently it is not matter.
What needed to be done was to send in two steps
send "olStatus "
expect "olStatus"
send "machine-123456\r"
expect -re {apc>$}
Related
I want to input y+enter to reply the question while executing copy tftp:something.
The script will send y, but \n does not work. It will stay (y/n)y and keep there without exiting or doing something else. I have tried \r, and the result was the same. Does anyone know the reason?
#!bin/bash
expect -c "
set timeout -1
spawn telnet x.x.x.x
expect \"username\"
send \"user\n\"
expect \"password\"
send \"pw\n\"
expect \"model\"
send \"copy tftp:something\n\"
expect \"(y/n)\"
send \"y\n\"
expect eof
"
exit 0
I prefer using \r to "hit enter".
Second, your entire bash script is expect, so remove the outer bash layer.
#!/usr/bin/expect -f
set timeout -1
spawn telnet x.x.x.x
expect "username"
send "user\r"
expect "password"
send "pw\r"
expect "model"
send "copy tftp:something\r"
expect "(y/n)"
send "y\r"
expect eof
If you have more logic in the bash part, to avoid quoting hell use a heredoc:
#!/bin/bash
expect <<'END_EXPECT'
set timeout -1
spawn telnet x.x.x.x
expect "username"
send "user\r"
expect "password"
send "pw\r"
expect "model"
send "copy tftp:something\r"
expect "(y/n)"
send "y\r"
expect eof
END_EXPECT
exit 0
I need to make a sftp connection with a password and download a file. There is an ip restriction so first of all i should make a ssh connection. I wrote a script but it stucks after connecting with ssh.
Note: i also tried doing it with an expect script but it also didn't work.
#!/usr/local/bin/
ssh test#test1.t.com
lftp sftp://test2:123456#test2.com
get "file.xls"
Edit: You can also see my expect code here.
#!/usr/local/bin/expect -f
expect -c "
spawn ssh test#test1.t.com
expect \"test\#test1\:\~\$\"
spawn sftp test2#test2.com
expect \"*assword:\"
send \"123456\r\"
expect \"sftp\>\"
send \"get file.xls\r\"
expect \"sftp\>\"
exit 1
";
I'm not sure exactly what you're trying to accomplish here. First, I'll address the problems in your expect script. Since your shebang line invokes expect, you don't need to wrap the expect body in a call to expect. That gets rid of all the backslashes. Next, you have 2 spawn calls, which raises questions about you're intent. I'm going to assume that you want to ssh to test1, then grab the file from test2 so the file exists on test1. This assumption changes the 2nd spawn to a plain send command.
#!/usr/local/bin/expect -f
set shell_prompt "test#test1:~$"
set sftp_prompt "sftp>"
spawn ssh test#test1
expect $shell_prompt
send "sftp test2#test2\r"
expect "*assword:"
send "123456\r"
expect $sftp_prompt
send "get file.xls\r"
expect $sftp_prompt
send "exit\r"
expect $shell_prompt
send "exit\r"
expect eof
Now, you can scp the file to your local machine. Let's put those 2 steps into one shell script:
#!/bin/sh
expect <<'EXPECT_SCRIPT'
set shell_prompt "test#test1:~$"
set sftp_prompt "sftp>"
spawn ssh test#test1
expect $shell_prompt
send "sftp test2#test2\r"
expect "*assword:"
send "123456\r"
expect $sftp_prompt
send "get file.xls\r"
expect $sftp_prompt
send "exit\r"
expect $shell_prompt
send "exit\r"
expect eof
EXPECT_SCRIPT
scp test#test1:file.xls .
When i run the script below, it connects the server but it disconnect before sending a command. How can i solve this problem.
#!/bin/bash
/usr/bin/expect << EOD
spawn telnet 31.168.109.31
sleep 2
expect ">"
sleep 1
send "my_password"
send "\n"
sleep 1
interact
As per your code you expect > before password. I am not getting you what is purpose of it but as for some example script look here. It's might be not an answer but probably help you.
#!/bin/bash
/usr/bin/expect << EOD
set timeout 200
spawn telnet 31.168.109.31
expect "login:"
send "root\r"
expect "password"
send "mypassword\r"
expect "root#"
#rest of your logic what you want.
Here is my script:
#!/usr/bin/expect
spawn /usr/bin/sftp user#place
expect "password:"
send "mysecret\n"
expect "sftp>"
send "mget dir/*.csv\n";
expect "sftp>"
send "quit\n"
It starts to download but after a few seconds, it sends the quit command and exits the program before the downloads are complete.
The only way I've successfully made it stop is to throw in an "interact" command but because I want to run this as a cron job, I don't want to just spawn processes that end up sitting.
Is there a way to accomplish this?
edit:
Someone will ask why I don't have a key setup... this is the only method allowed to me by the vendor.
Adding the line set timeout -1 appears to have fixed this problem
The whole script should look as such:
#!/usr/bin/expect
set timeout -1
spawn /usr/bin/sftp user#place
expect "password:"
send "mysecret\n"
expect "sftp>"
send "mget dir/*.csv\n";
expect "sftp>"
send "quit\n"
Well, if you can use Perl:
use Net::SFTP::Foreign;
my $sftp = Net::SFTP::Foreign->new('user#place', password => 'mysecret');
$sftp->mget("dir/*.csv", '.',
on_error => sub {
warn "unable to copy '$_[1]{filename}':".$sftp->error."\n";
});
You will have to install Net::SFTP::Foreign and IO::Pty (also available as packages in several linux distributions).
I try to backup a Linkproof device with expect script and i have some trouble. It's my first script in expect and i have reach my limits ;)
#!/usr/bin/expect
spawn ssh #IPADDRESS
expect "username:"
# Send the username, and then wait for a password prompt.
send "#username\r"
expect "password:"
# Send the password, and then wait for a shell prompt.
send "#password\r"
expect "#"
# Send the prebuilt command, and then wait for another shell prompt.
send "system config immediate\r"
#Send space to pass the pause
expect -re "^ *--More--\[^\n\r]*"
send ""
expect -re "^ *--More--\[^\n\r]*"
send ""
expect -re "^ *--More--\[^\n\r]*"
send ""
# Capture the results of the command into a variable. This can be displayed, or written to disk.
sleep 10
expect -re .*
set results $expect_out(buffer)
# Copy buffer in a file
set config [open linkproof.txt w]
puts $config $results
close $config
# Exit the session.
expect "#"
send "logout\r"
expect eof
The content of the output file:
The authenticity of host '#IP (XXX.XXX.XXX.XXX)' can't be established.
RSA key fingerprint is XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.
Are you sure you want to continue connecting (yes/no)? #username
Please type 'yes' or 'no': #password
Please type 'yes' or 'no': system config immediate
Please type 'yes' or 'no':
Like you can see, the result of the command is not in the file. Could you, please, help me to understantd why ?
Thanks for your help.
Romuald
All of your "expect" statements are timing out because the text they are waiting for does not match the text that actually appears. Let's examine the first one or two, the others are all the same.
You say:
expect "username:"
But what it actually receives from ssh is:
The authenticity of host '#IP (XXX.XXX.XXX.XXX)' can't be established.
RSA key fingerprint is XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.
Are you sure you want to continue connecting (yes/no)?
This does not contain the string "username:" so the expect command will time out, and the script will move on to the next command:
send "#username\r"
We can see it does send that:
Are you sure you want to continue connecting (yes/no)? #username
But that's not a valid answer to this question.
And the rest of the output is the same idea over and over.
As #joefis mentioned, you do need to catch the yes/no from ssh.
I've copied this from my response in serverexchange as its highly relevant here
You will want to avoid using "Password:" if you monitor your strings
during login, you will find that it is not always capitalized.
Changing your expect to -re "(.*)assword:" or "assword:" tends to be
much more effective for catching the line.
If you find that the timings are still too quick you can put a sleep
1; before your send
This is what i use for expect
expect {
#When asked about authenticity, answer yes then restart expect block
"(yes/no)?" {
send "yes\n"
exp_continue
}
"passphrase" { send "\r" }
-re "(.*)assword:" { sleep 1; send -- "password\r" }
-re $prompt { return }
timeout { puts "un-able to login: timeout\n"; return }
eof { puts "Closed\n" ; return }
}
so a couple of things, this will allow for expect to respond to any of these results on a single expect, it will then only continue to more of the code if a return statement is found. I would recommend setting a prompt value as it becomes help full to detect if your commands are complete or your login was indeed successful.