How to send Ctrl + a then d in Expect - expect

So I am trying to spawn a shell to a remote server then make a screen run some commands and then detach from said screen by doing:
#!/usr/bin/expect
set server [lindex $argv 0]
spawn s "$server"
expect "#" { send "screen -S test\r" }
expect "#" { send \someescapeheretoreplicate ctrl + a then d to tell screen to detach }
interact
But I have no idea what those escape sequences are called so am unable to look up a table of them or what not.

If I recall:
send "\x01"; send "d"
Where \x01 is the value of Ctrl-A

for Ctrl+A
send "\x01"
for Ctrl+D
send "\x04"

Related

"Expect" command line script to connect to VPN and enter password

I am trying to write an "Expect" script to connect to a VPN...
Trying to write and expect (https://likegeeks.com/expect-command/) script to connect to a vpn, is this the right idea:
The commands to connect are:
sudo vpnName [ENTER] *Password* [ENTER] Random number 1-100 [ENTER] [ENTER]
So the expect script would be something like:
#!/usr/bin/expect -f
set randNum [(( ( RANDOM % 100 ) + 1 ))]
send -- "sudo vpnName\r"
send -- "*password*\r"
send -- "randNum\r \r"
You are trying to combine a bash expression with tcl (language expect is using)
Use instead:
set randNum [expr {int(rand()*100) + 1}]
In expect, you need to spawn a process before you can interact with it:
#!/usr/bin/expect -f
set randNum [expr {int(rand()*100) + 1}] # as per #Sorin's answer
spawn sudo vpnName
expect "assword" # wait for the password prompt
send -- "*password*\r"
expect "whatever matches the random number prompt"
send -- "$randNum\r\r"
# this keeps the vpn process running, but returns interactive control to you:
interact
A tip: while debugging expect code, launch it with expect -d -f file.exp -- this is very valuable to let to see if your expect patterns are matching as you think they should.

What does it mean to combine interact with return in expect?

I want to use shell and expect to log in to the server with only one command.
But when interact and return are used in one statement, I don't understand what they mean.In addition, "Password" will only appear when SSH link multiplexing is disconnected, so I hope that when "Password" does not appear, it will not send "mypassord".
So how to write scripts to deal with these two situations in a unified way?
When SSH multiplexed links were established, my script was stuck in "expect "Password"".How to deal with it?
In addition, I would like to ask what does the -o parameter mean after the interact? And what is the meaning of using interact and return together?
What's the difference between "send --" and "send "?
I have enabled SSH master connection. Before I log on to the server, I need to first enter the password, and then enter a number to represent which machine I log on to. But when SSH multiplexed links are established, the option of entering passwords becomes redundant.
#!/usr/bin/expect
# ssh command
set cmd [lindex $argv 0]
set relay_num [lindex $argv 1]
set timeout -1
# run ssh command
spawn bash -c "$cmd"
expect "Password*"
send "mypassord\r"
interact -o -nobuffer -re "Option" return
send -- "$relay_num\r"
interact
In combination with the -o switch, that line is looking at the output of the command for the regex "Option". The return will cause the interact command to end and the script continues to the send command (that is explained in the man page).
I think it would be more clear to use expect "Option" instead.

expect telnet to multiple cisco devices and execute show run

I have the following scripts which is supposed to pull the IP address from a file device-list.txt and then telnet to the device, login and execute a show run. The script logs in to the device successfully, but gives me an error after that. Any ideas where im going wrong?
for device in `cat device-list.txt`; do ./test4 $device;done
cat test4
#!/usr/bin/expect -f
set hostname [lindex $argv 0]
set user myusername
set pass mypassword
set timeout 10
log_file -a ~/results.log
send_user "\n"
send_user ">>>>> Working on $hostname # [exec date] <<<<<\n"
send_user "\n"
spawn telnet $hostname
expect "Username:"
send "$user\n"
expect "Password:"
send "$pass\n"
expect "#"
send “term len 0\n”
send “show running-config\n”
expect “end\r”
send “\n”
send “exit\n”
User Access Verification
Username: myusername
Password:
ROUTER#usage: send [args] string
while executing
"send “term len 0\n”"
(file "./test4" line 26)
Your problem is due to incorrect double quotes. You have to use double quotes ", not smart quotes “
send “term len 0\n” ; # Wrong
send "term len 0\r"; # Correct
Note :
Basically, Expect will work with two feasible commands such as send and expect. If send is used, then it is mandatory to have expect (in most of the cases) afterwards. (while the vice-versa is not required to be mandatory)
This is because without that we will be missing out what is happening in the spawned process as Expect will assume that you simply need to send one string value and not expecting anything else from the session.
So, we recommend to use expect after each send, to make sure our commands actually sent to the spawned process. (You have not used expect after sending some commands such as term len 0\r). Also, use \r instead of \n.

Expect script for checking ssh connection for a list of ips

Can anyone help me in creating an expect script to just do an SSH on a list of servers and check if it was fine. I do not need to interact, do not need to fire any command on each server, I just want to do an ssh and come out, with a return code mentioning whether it was successful or not.
Expect is important here, as I do not have an option to setup a passwordless connection. Also there is a possibility that passwordless connection is setup on some of those servers.
I tried something like:
#!/usr/local/bin/expect
set timeout 10
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
set prompt "(>|%|\\\\\\\$|#|]|) \$"
spawn ssh "$user\#$ip"
expect "Password:"
send "$password\r"
send "echo hello\r"
expect "hello"
send "exit\r"
But this gets stuck on the first server, and does nothing after that.
Thanks,
Piyush
A generalized idea can be having a procedure to spawn the ssh and close the connection which will maintain the connections local to the scope, so that global spawn_id won't get affected at all.
#!/usr/bin/expect
proc isHostAlive {host user pwd} {
# We escaped the `$` symbol with backslash to match literal '$'
# Commonly used prompt types
set prompt "#|%|>|\\\$"
set timeout 60
spawn ssh $user#$host
expect {
timeout {return FAIL}
"(yes/no)" {send "yes\r";exp_continue}
"password:" {send "$pwd\r";exp_continue}
-re $prompt
}
set msg "Hello World"
send "echo $msg\r"
expect {
timeout {return FAIL}
"\r\n$msg"
}
send "exit\r"
expect {
timeout {return FAIL}
eof
}
return PASS
}
# Lists to maintain the each host's information
set serverList {server1 server2 server3}
set userList {user1 user2 user3}
set pwdList {pwd1 pwd2 pwd3}
# Looping through all the servers and checking it's availability
foreach server $serverList user $userList pwd $pwdList {
puts "\n==>Status of $server : [isHostAlive $server $user $pwd]\n"
}
With exp_continue, we can handle even if any host does not have password. Basically exp_continue will cause the expect to run again. So, among the mentioned phrase whichever comes, it will be handled. i.e. if expect sees (yes/no), it will send yes, if expect sees password, it will send the password value and so on. Then expect will continue to wait for the whole set of phrases again.
The reason why I have added yes/no is because if suppose the host's RSA fingerprint needs to be saved.
After successful login, I am echoing Hello World and expecting for the echoed message. If you have noticed, I have used \r\n$msg in the expect statement. Why do we need \r\n here ?
Here is why. Whenever we send command that will be seen by the expect also and it will try to match against that too. If it matched, it will proceed as such.
Sample echo command output
dinesh#dinesh-VirtualBox:~/stackoverflow$ echo Hello World
Hello World
dinesh#dinesh-VirtualBox:~/stackoverflow$
The string we want to expect is already available in the send command. So, to make sure the matching expect string is only from the actual echoed response, I have added \r\n which will help us in matching what is necessary.
Then at last of the proc, I am sending exit command which will close the ssh connection and to match the same eof (End Of File) is used. In all sort of failure cases, the procedure will return FAIL.

Expect script failing to continue

I have an expect script which is logging onto a device and sending a command, however the script completes without finishing, its like the last expect isn't being picked up.
How do I enable debugging to watch the script progress so I can identify where the issues is?
My script looks like this...
#!/usr/bin/expect
set hostname [lindex $argv 0]
set username "a.user"
set password "a.pass"
spawn telnet $hostname
expect "Username:" {
send "$username\r"
expect "Password:"
send "$password\r"
}
expect "#" {
send "sh ver\r"
}
It stops processing at the below line;
expect "#" {
however I can clearly see the # in the last output.
Thanks

Resources