Unix - Expect Not Working While Executing Commands - linux

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)

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.

Linux expect command without interact directive not working

I want to login from 192.168.119.128 to 192.168.119.129 automatic and run some commands, so I write an expect script.
a.sh
#!/usr/bin/expect -f
set timeout 5
spawn ssh root#192.168.119.129
expect "password" {send "123456\r"}
expect "]#" {send "touch /tmp/a.txt\r"}
#interact
The output is:
kaiwen#kaiwen-virtual-machine:~/Work$ ./a.sh
spawn ssh root#192.168.119.129
root#192.168.119.129's password:
Last login: Sun Jan 22 17:36:21 2017 from 192.168.119.128
[root#localhost ~]# kaiwen#kaiwen-virtual-machine:~/Work$
I login successfuly, but it seems touch /tmp/a.txt command is not run.
When I uncomment the last line #interact of a.sh, it works, and the file a.txt is created.
#!/usr/bin/expect -f
set timeout 5
spawn ssh root#192.168.119.129
expect "password" {send "123456\r"}
expect "]#" {send "touch /tmp/a.txt\r"}
interact
Here is the output:
kaiwen#kaiwen-virtual-machine:~/Work$ ./a.sh
spawn ssh root#192.168.119.129
root#192.168.119.129's password:
Last login: Sun Jan 22 17:41:23 2017 from 192.168.119.128
[root#localhost ~]# touch /tmp/a.txt
[root#localhost ~]#
Why without the interact directive the script work incorrect? Thanks.
Without interact the Expect script will exit after the last command expect "]#" and it'll kill the spawned process. It's just like you close the SSH client application (like PuTTY) window when the shell is still alive running.
The interact is a long-running command which waits for the spawned process to exit.

How to catch standard errors from expect script

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"

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

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}
}

Resources