How to catch standard errors from expect script - linux

the following expect script will remove the file /var/tmp/file on remote machine
but before that the expect script do ssh on the remote machine ,
I put the 2>/tmp/errors in order to catch error from ssh
but I notice that in spite ssh to remote send error , I not see the errors from /tmp/errors file
but when I tryed manual the
ssh $LOGIN#$machine
then ssh fail on WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED
but from the expect I cant to catch this errors in /tmp/erros
please advice what’s is wrong ? why 2>/tmp/errors not capture the errors?
expect_test=`cat << EOF
set timeout 50
spawn ssh $LOGIN#$machine 2>/tmp/errors
expect {
")?" { send "yes\r" ; exp_continue }
word: { sleep 1 ; send $PASSORD\r}
}
expect > {send "sleep 1\r"}
expect > {send "rm -f /var/tmp/file\r"}
expect > {send exit\r}
expect eof
EOF`
expect -c "$expect_remove_file"

spawn does not understand I/O redirection. Replace
spawn ssh $LOGIN#$machine 2>/tmp/errors
with either
spawn ssh $LOGIN#$machine -E /tmp/errors
# -E log_file tells ssh where to write the error log instead of stderr
or
spawn sh -c "ssh $LOGIN#$machine 2>/tmp/errors"

Related

expect ssh reg_ex for remote prompt

I have an shell script which uses expect to launch a ssh session to another server and list a directory. It works fine but my question is what is the best way to handle remote prompts after logging in? For example, here is what I have so far:
# Wait for the prompt on a remote ssh server
-re "\[%|>|\$|#\] $" {
send "ls -1t /home/user/\r"
expect {
"*not found" {
puts "\nDirectory not found\n"
exp_continue
}
timeout { puts "\ntimeout happened\n" }
-re "\[%|>|\$|#\] $" {
puts "Exiting..."
send "exit\r"
return
}
}
}
So, after a successful login the expect script waits for the prompt before sending the ls -1t /home/user/ command. The prompt can be different depending how how the ssh destination is setup. So far I'm checking for
-re "\[%|>|\$|#\] $"
prompts handled so far....
%
>
$
#
I would like to make this as generic as possible so I know the destination ssh server is ready to receive the ls -1t /home/user/ command.
Is there a better way to do this or should I add more cases to the reg_ex in my expect script?
I've also tried -re ". $" but this doesn't work

Unix - Expect Not Working While Executing Commands

I am trying to execute commands on a remote UNIX host using send and expect ssh module, but even if the script logs in to the server successfully it does not execute commands.
#!/usr/bin/expect
set timeout 60
spawn ssh xxxx#xxxxxx
expect "yes/no" {
send "yes\r"
expect "*?assword" { send "xxxxxx\r" }
} "*?assword" { send "xxxxxxx\r" }
expect "$ "
#sleep 5
send "ps -aef \r"
Output
[xxxxx#xxxxxx Scripts]$ ./TestExpect.sh
spawn ssh xxxxx#xxxxxx
xxxxxx#xxxxxx's password:
Last login: Wed May 9 02:05:47 2018 from xxxxxxxxx
Kickstarted on 2015-05-12
[xxxxx#xxxxx ~]$ [xxxxxx#xxxxx Scripts]$
The Prompt looks like below
[aacdd123#linprod345 ~]$
Issue may be because, you are not expecting anything after sending the ps -aef. Hence the expect spawn process has exited before printing the output.
Try adding few more commands after the sending ps -aef
send "ps -aef\r"
expect $prompt
send "echo hello\r"
expect $prompt
Try looking into the expect_out buffers too, which will give you the captured streams.
puts $expect_out(buffer)

how to acquire the return value of a command in ssh accessed by expect?

After i use expect access ssh, and run particular command in it. How could i get the actually return value of that command and set it to the return value of expect or an env variable(better)?
I am not so familiar with expect, so a few lines to show how the capture thing works would help a lot. Many thanks.
You do it the same way you would sitting at a terminal: echo $? (I assume your remote shell is sh/ksh/bash/...)
#!/usr/bin/expect -f
set host remote_host
set user remote_username
set prompt {\$ $}
set cmd {grep not-found /etc/passwd}
log_user 0
spawn ssh -l $user $host
expect -re $prompt
send "$cmd\r"
expect -re $prompt
send -- "echo \$?\r"
expect -re "\r\n(\\d+)\r\n.*$prompt"
set rc $expect_out(1,string)
send -- "exit\r"
expect eof
puts "return code from '$cmd' on $host = $rc"

Modify expect-based SSH script to work on machines that don't require a password

The following expect script works fine when the Linux machine asks for a password after login. But some of our Linux machines don't need a password for SSH (we can login without a password), so I need to change the expect script in order to support machines without a password. How can I do that?
$ expect_test=`cat << EOF
set timeout -1
spawn ssh $IP hostname
expect {
")?" { send "yes\r" ; exp_continue }
word: {send "pass123\r" }
}
expect eof
EOF`
$ expect -c "$expect_test"
When running on a machine that needs a password:
$ IP=10.17.18.6
$ expect -c "$expect_test"
spawn ssh 10.17.18.6 hostname
sh: /usr/local/bin/stty: not found
This computer system, including all related equipment, networks and network devices (specifically including Internet access),is pros
yes
Password:
Linux1_machine
When running on a machine that doesn't need a password:
$ IP=10.10.92.26
$ expect -c "$expect_test"
spawn ssh 10.10.92.26 hostname
sh: /usr/local/bin/stty: not found
Linux15_machine
expect: spawn id exp5 not open
while executing
"expect eof"
Use this expect command:
expect {
")?" {send "yes\r"; exp_continue}
word: {send "pass123\r"; exp_continue}
eof
}
That way, if EOF is encountered before "password:", the script will act normally.
Change you timeout from -1 to something else, this will cause expect to move on to the next line if the expected string does not show up within the given timeout.
The current value, -1 causes it to block forever if not password is prompted for.
UPDATE:
set timeout 5
spawn ssh $IP hostname
expect {
")?" { send "yes\r" ; exp_continue }
word: {send "pass123\r" }
eof {exit}
}

spawn_id: spawn id exp6 not open

I know that this issue is already mentioned here, but the solution does not work for me.
I have this script (let's name it myscript.sh) that spawns a process on remote environment and that should interact with it.
#!/usr/bin/expect
log_user 0
set timeout 10
spawn ssh -o PubkeyAuthentication=no [lindex $argv 0] -n [lindex $argv 1]
expect "password:" {send "mypassword\r"}
expect "Continue to run (y/n)" {send "n\r"}
interact
When I call this script on local environment...
myscript.sh user#host "command1;./command2 parameter1 parameter2"
I get the above error at line 7 (interact)
Any ideas??
I suspect the expect is not able to find out(matching) the pattern you are sending.
expect "password:" {send "mypassword\r"}
expect "Continue to run (y/n)" {send "n\r"}
Check out again whether the "password:" and "Continue to run (y/n)" are in correct CAPS.
If still getting the same error, you can try using regular expression.
Try to do a normal ssh without script. See if it works. Sometimes the remote host identification changes, and the host has a new ip or new key. Then it helps to remove the old key with ssh-keygen -f ~/.ssh/known_hosts -R old_host, or something similar.
I had this problem and it was down to using the wrong port.
/usr/bin/expect <<EOF
spawn ssh-copy-id -i $dest_user#$ip
expect {
"yes/no" {
send "yes\r";exp_continue
} "password" {
send "$passwd\r"
} eof {
exit
}
}
expect eof
EOF
I ran into this issue as well but it was due to me creating/editing the following file for an unrelated item:
~/.ssh/config
Once I deleted that, all my scripts began working and I no longer got that issue with my expect file.

Resources