How to spawn telnet session based on user input - bash

I created a script that queried everything on a specified device, however too much data is printed and I'd like to be able to query specific areas of the device configuration depending what arguments are passed.
My initial script which prints everything works fine
#!/usr/bin/expect
set hostName [lindex $argv 0]
set timeout 2
spawn telnet $hostName
expect -re "login"
send "xxx\n"
expect -re "Password:"
send "<password>"
sleep 0.5
send "<query 1>"
sleep 0.5
send "<query 2>"
interact
Now I am creating a help section which involves including bash, and am having some trouble getting both expect & bash to work at the same time, along with being able to interact at the end. Does anyone have any advice?
with the below, the help function works but the send commands etc. don't work
#!/bin/bash
#!/usr/bin/expect -f
With the below I am unable to run the help menu
#!/usr/bin/expect -f
#!/bin/bash
I get this error:
invalid command name "Help()"
while executing
"Help()"
(file "./xxx" line 5)
Does anyone have any advice?

Related

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.

why expect shell script for 'obexctl' not working as Expected

I want to send a file using bluetooth from one device to another device. For that i am using obex which has a command called 'obexctl'. It works as
described in this ... Please Take a look into this Doc
This is how sending file works. For automating this process i have written one shell script using expect. which is as below.
#!/usr/bin/expect -f
set address [lindex $argv 0]
set prompt "#"
spawn obexctl
sleep 2
expect -re $prompt
send "connect $address\r"
sleep 5
send "quit\r"
but it didnt work. It doesnt fully execute that connect command.and exit the code. Please let me know if any of you know the solution.

Bash scripting with expect. Set parameters to multiple test boards

I'm working on a small project for school. I'm using 15 or so tuners to emulate a Cell network. I'm by no means well versed in scripting yet. I'm an EE who usually googles until I have some frankencode capable of my purposes.
The goal is the set up all the modules quickly so I thought to automate the process with a script. This requires ssh, and so far I have to manually type in the password each time. This morning I set up a basic test with both Expect and sshpass. In either case I can correctly log in, but not give instructions to the remote machine.
I was reading that sshpass has difficulty with sending remote instruction, correct me if I'm wrong.
/usr/bin/expect << EOF
spawn ssh root#<IP>
expect "(yes/no)?" #Are you sure you want to connect nonsense
send "yes\r"
expect "password"
send "$pass\r"
I tried a few things here to get the device to receive instruction
interact
cat /pathto/config.txt
#or
send "cat /pathto/config.txt
#the real goal is to send this instruction
sqlite3 /database.db "update table set param=X"
EOF
You might as well make it an expect script, not a shell script
#!/usr/bin/expect -f
and then pass the IP address to the script as a command line argument
expect myloginscript.exp 128.0.0.1 the_password
In the expect script, you'll grab that IP address from the arguments list
set ip [lindex $argv 0]
set pass [lindex $argv 1]
(Putting the password on the command line is not good security practice. You can research better methods of passing the password to your expect script.)
To use ssh, you'll be asked "are you sure" only the first time to connect, so let's make that conditional. That is done by letting the expect command wait for several patterns:
spawn ssh root#$ip
expect {
"(yes/no)?" {
send "yes\r"
# continue to wait for the password prompt
exp_continue
}
"password" {
send "$pass\r"
}
}
Once that is sent, you should expect to see your shell prompt. The pattern for this is up to your own configuration but it typically ends with a hash and a space.
expect -re {# $}
Now you can automate the rest of the commands:
send "cat /pathto/config.txt\r"
expect -re {# $}
# note the quoting
send "sqlite3 /database.db \"update table set param='X'\"\r"
expect -re {# $}
At this point, you'll want to log off:
send "exit\r"
expect eof
On the other hand, if you set up ssh private key authentication (see ssh-keygen and ssh-copy-id), you can just do this:
ssh root#IP sqlite3 /database.db "update table set param='$X'"
and not have to get into expect at all.

How to use error codes inside bash script

Apologies if this has been asked before, I was unable to find an answer...
I have created a bash script for OS X to mount an AFP share. The script works successfully and allows a user to type their username and password into a graphical popup using cocoa dialog
My issue is that if the username and password are entered incorrectly, I want to be able to display a new pop up window explaining this.
I was trying to do this based on the exit status of the script but the script returns 0 regardless of whether or not the mount was successful
The script is as follows;
cd=/etc/cocoaDialog.app/Contents/MacOS/cocoaDialog
rvUsername=($($cd standard-inputbox --title "Network Mount" --informative-text "Please enter your username"))
username=${rvUsername[1]}
rvPassword=($($cd secure-standard-inputbox --title "Network Mount" --informative-text "Please enter your password"))
password=${rvPassword[1]}
mkdir "/Volumes/Test"
expect <<- DONE
set timeout -1
spawn /sbin/mount_afp -i "afp://servername/Software" /Volumes/Test
expect "*?ser:*"
send "$username\n"
expect "*?assword:*"
send "$password\r"
expect EOF
DONE
If I run this via Terminal or Textmate, I receive the following (as an example)
spawn /sbin/mount_afp -i afp://server/Software /Volumes/Test
User: username
Password:
mount_afp: the volume is already mounted
Program exited with code #0 after 7.32 seconds.
So mount_afp is giving me a message, which I would then like to use in my script...but the exit code is 0 and I don't know how else to get hold of that message to use
Any ideas? (Hope that makes sense!)
To get the exit code of the spawned command, use something like this:
# wait for the command to end : wait for the prompt $ followed by space
expect "\\$ "
send "echo \$?\r"
expect -re "(\\d+)" {
set result $expect_out(1,string)
}
send_user "command exit with result code : $result"
This will take the content of the variable $? (which is the exit code of the prevously ended command) and save it to $result.
Thanks for the responses all, helped point me in the right direction
I ended up taking this approach and setting the expect command as a variable
output=$(su -l $loggedInUser -c expect <<- DONE
set timeout -1
spawn /sbin/mount_afp -i "afp://$serverName" /Volumes/mount
expect "*?ser:*"
send "$username\n"
expect "*?assword:*"
send "$password\r"
expect EOF
DONE)

Automating pear install with expect

I'm working on a small script to try and automate the installation of pear on a system should it be missing - basically, taking the interactive portions of the installation process and making them non-interactive so all I need to do is execute the script and it does it for me on its own. This is my first time trying to use expect and it's, well, not what I expected.
Sample code below:
/usr/bin/expect <<EOD
set timeout 20
set number [lindex $argv 0]
set path [lindex $argv 1]
spawn php -q go-pear.phar
expect "1-11, 'all' or Enter to continue:"
send "$number\r"
interact
expect "Installation base ($prefix) [/usr/local] :"
send "$path\r"
interact
EOD
This is not quite working at the moment as it's trying to fill in the /usr/local portion in the first menu as follows:
1-11, 'all' or Enter to continue: invalid command name "/usr/local"
while executing
"/usr/local"
invoked from within
"expect "Installation base () [/usr/local] :""
Can anyone show me what I'm missing here? Also, I'd like to get this so I don't have to run it as ./script $var0 $var1 but rather just run it as ./script with everything being contained within and filled in, but not sure how to do that.
Thanks in advance for any help you can offer.
One problem is that the [...] inside the string tells expect to execute a command. I think you need to escape them with \[...\].
Hope this helps a little =)
I ended up figuring this out. In case anyone else wants to do something similar, here's what worked for me:
/usr/bin/expect <<EOF
set send_slow {1 .1}
set timeout -1
spawn php -q go-pear.phar
expect "1-11, 'all' or Enter to continue:"
sleep .1
send -s -- "1\r"
expect -exact "1\r"
sleep .1
send -s -- "/usr/local\r"
expect -exact "/usr/local\r"
expect "1-11, 'all' or Enter to continue:"
sleep .1
send -s -- "\r"
expect -exact "\r"
expect EOF

Resources