Why spawn scp does not work correctly? - linux

Below is my script containing spawn scp related script.
spawn scp -r /usr/local/clo/Jenkins.zip root#xu.domain.com:/usr/local/clo
expect "password:"
send "111111\r"
expect "*\r"
expect "\r"
But when I execute it, it output the following log and it can not transfer the file correctly.
**
spawn scp -r /usr/local/clo/Jenkins.zip root#xu.domain.com:/usr/local/clo
root#xu.domain.com's password:
Jenkins.zip 0% 0 0.0KB/s --:-- ETA
**
I was wondering how does the '0%' happen? If I manually execute the scp script from console, it can send the file completely.

I suspect this happens because the output of the spawned process includes \r (carriage return) characters when displaying the progress meter, try to add expect eof at the end of your Expect script.
But to deal with timeout problems, it should be better to detect the progress meter, using exp_continue to continue executing while the progress meter is displayed:
spawn scp -r /usr/local/clo/Jenkins.zip root#xu.domain.com:/usr/local/clo
expect "password:"
send "111111\r"
expect {
"ETA" {exp_continue}
"100%" {}
}
expect eof
You could also add exp_internal 1 at the beginning of the script (it reports internal activity of the expect command).

Related

How to list a directory with expect via sftp connection

I have this expect script but the list of files does not present me correctly.
expect.dat
set timeout 10000
spawn sftp -o ConnectTimeout=3 user#192.1.6.6
expect "*?assword*"
send "tech\r"
expect "sftp>"
send "cd /global/scripts/log\r"
expect "sftp>"
send "ls 20220703*\r"
expect "sftp>"
send "bye\r"
Expect command
expect expect.dat
Result
spawn sftp -o ConnectTimeout=3 user#192.1.6.6
Password:
Connected to user#192.1.6.6.
sftp> cd /global/scripts/log
sftp> ls 20220703*
20220703_A.log 20220703_A.xls
20220703_E.log 20220703_E_r.log
sftp> You have new mail in /var/spool/mail/dm
how to get this result?
20220703_A.log
20220703_A.xls
20220703_E.log
20220703_E_r.log
First, use the sftp command ls -1 20220703* to produce output in a single column.
Next, use log_user 0 and spawn -noecho sftp ... to hide all the excess output.
Last, and the trickiest part, capture the ls output so that can be printed out cleanly: we have to handle the fact that the command we just "typed" will be given back to us.
set ls_cmd "ls -1 20220703*"
send "$ls_cmd\r"
# capture the command's output
expect -re "$ls_cmd\r\n(.*)\r\nsftp>"
puts $expect_out(1,string)
send "bye\r"
expect eof # wait for sftp to exit cleanly
expect gives you the process's output using \r\n line endings.

Two commands or command pipe command - Spawn Expect

I'm trying to execute a expect script into bash script, but when I try to execute the shell without "| tee -a xxx.log" (where xxx.log is a file than I want to write to record the ssh session).
This code works fine:
comlog="ssh $USR#192.168.228.20"
expect -c"
spawn \"$comlog\"
expect \"Password:\"
send \"$PASS\r\"
interact
"
But when I try to add the "tee -a" command to save the ssh session the issue is
invalid command name "ssh"
while executing
This is the complete command where I obtain the error message
comlog="ssh $USR#192.168.228.20 | tee -a /home/xxx.log"
expect -c"
spawn \"$comlog\"
expect \"Password:\"
send \"$PASS\r\" #Already Obteined
interact
"
I tried to change the "comlog" var as this ways but doesn't work :(
cssh $USR#192.168.228.20 \| tee -a /home/xxx.log
Does anyone know another way to save the ssh session started from expect? Or how can I send those two commands in same spawn command.
You can capture the expect session output this way:
comlog="ssh $USR#192.168.228.20"
expect -c"
spawn \"$comlog\"
expect \"Password:\"
send \"$PASS\r\" #Already Obteined
interact
" >/home/xxx.log
If you want to put shell metacharacters like the pipe, you'll have to spawn a shell to handle them. Also using a here-doc can help a lot with quoting
comlog="ssh $USR#192.168.228.20 | tee -a /home/xxx.log"
expect <<"END_EXPECT"
spawn sh -c "$comlog"
... rest of expect script
END_EXPECT

Expect script error send: spawn id exp4 not open while executing "send "password""

I'm trying to run an expect script but I have an error:
send: spawn id exp4 not open
while executing
"send "password"
My script is very simple:
#!/usr/bin/expect -f
#!/usr/bin/env expect
#!/usr/bin/env export
#!/bin/sh
#!/bin/bash
spawn sftp -o IdentityFile=/home/localUser/MyPrivKeys_open.ppk user#123.123.123.123
expect "sftp.gatewayEnter passphrase for key '/home2/localUser/MyPrivKeys_open.ppk':"
send "passphrase\r"
expect "sftp>"
send "cd /home/localUser/localPath \r"
expect "sftp>"
send "mget myfile.xml /home/localUser/localPath \r"
set timeout 5
interact
What I do is editing my expect script in notepad.exe but when i upload my script i have to run next commands:
dos2unix bash.sh -> converts dos file to a Unix file
chmod +x bash.sh -> gives execution permission
And finally i run my script:
./bash.sh
But after that it sends that error.
It is something really weird because i have another .sh file with the same structure and i am only changing paths where i get files
I think i need some help about it.
Thanks.
I have already fix it, it was an error in dos2unix command. I had to code it again over Ubuntu for avoiding to run dos2unix command.

expect auto login sucess, but can't exec any command

the shell code:
~ cat test_longin.sh
#!/usr/bin/expect
set timeout 120
spawn /usr/bin/ssh fuyou#target.server
expect "*assword*"
send "fuyou\n"
interact
When I type ./test_login.sh, it can login target servers successfully, but when I execute ls command, the console doesn't output any text. So I can't exec any commond on target server. Is the interaction problematic?
I think you should expect something after send, but not use command "interact" immediately.
xxx:/home/username/temp # cat t1.exp
#!/usr/bin/expect
spawn ssh serverx
expect "#"
send "ls -l\r"
expect "#"
interact

How to automate telnet session using Expect?

I'm trying to write an expect script to automate telnet. This is what I have so far.
#!/usr/bin/expect
# Test expect script to telnet.
spawn telnet 10.62.136.252
expect "foobox login:"
send "foo1\r"
expect "Password:"
send "foo2\r"
send "echo HELLO WORLD\r"
# end of expect script.
Basically, what I want to do is telnet to the following IP address and then echo HELLO WORLD. However, it seems that the script fails after attempting to telnet...I'm not sure if it's able to accept login and password input, but it is not echoing HELLO WORLD. Instead, I just get this output:
cheungj#sfgpws30:~/justin> ./hpuxrama
spawn telnet 10.62.136.252
Trying 10.62.136.252...
Connected to 10.62.136.252.
Escape character is '^]'.
Welcome to openSUSE 11.1 - Kernel 2.6.27.7-9-pae (7).
foobox login: foo1
Password: foo2~/justin>
It's hard to tell, but from the output you're pasting it looks like:
Your script isn't waiting for login to complete before sending the next command.
Your script is exiting and closing the process before you can see any output.
There are no guarantees in life, but I'd try this as a first step:
#!/usr/bin/expect -f
spawn telnet 10.62.136.252
expect "foobox login:"
send "foo1\r"
expect "Password:"
send "foo2\r"
# Wait for a prompt. Adjust as needed to match the expected prompt.
expect "justin>"
send "echo HELLO WORLD\r"
# Wait 5 seconds before exiting script and closing all processes.
sleep 5
Alternatives
If you can't get your script to work by manually programming it, try the autoexpect script that comes with Expect. You can perform your commands manually, and autoexpect will generate an Expect typescript based on those commands, which you can then edit as needed.
It's a good way to find out what Expect actually sees, especially in cases where the problem is hard to pin down. It's saves me a lot of debugging time over the years, and is definitely worth a try if the solution above doesn't work for you.
You're sending the echo command without first expecting the prompt. Try:
# after sending the password
expect -re "> ?$"
send "echo HELLO WORLD\r"
expect eof
Have you seen this StackOverflow Question?
He seems to have got things working by using curly braces.
Here is a simplified version
#!/usr/bin/expect
# just do a chmod 755 one the script
# ./YOUR_SCRIPT_NAME.sh $YOUHOST $PORT
# if you get "Escape character is '^]'" as the output it means got connected otherwise it has failed
set ip [lindex $argv 0]
set port [lindex $argv 1]
set timeout 5
spawn telnet $ip $port
expect "'^]'."

Resources