Linux - GeneralThis Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Hello. First time posting. I have written an expect command to ssh and sudo to a server and run a command.
I must write this code to allow for any variances or errors from the user (Ex, no ssh keys, no passwordless sudo, no sudo privileges, account locked out, wrong username, wrong password, invalid hostname, host not reachable, etc.).
Basically, I must allow for anything that can go wrong - within reason.
The code is working fine with valid and invalid input except for when I setup the user to have password-less sudo "NOPASSWD" in /etc/sudoers. Then I get garbage output which is not what I'm expecting.
I have included "send_user" statement for debugging purposes and they will not be included in the final version.
Here are the variables I use in my script which are prompted for prior to executing expect.
expect –c “
set timeout 2
log_user 0
stty -echo
spawn -noecho ssh -q -o NumberOfPasswordPrompts=1 StrictHostKeyChecking=no -o ConnectTimeout=3 \”${hn}\” -l \”${sshUser}\” -t \“/usr/bin/sudo -k ; /usr/bin/sudo ls -ld /root/Desktop 2>/dev/null\” 2>/dev/null
# Expect ssh password prompt.
expect {
-nocase password: {
send_user \”ssh password was triggered\”
send \”${sshPassword}\”
}
timeout {
send_user \“ssh timout was triggered\”
}
eof {
send_user \“ssh eof was triggered\”
}
}
# Expect sudo password prompt.
expect {
sudo {
send_user \“sudo password was triggered\”
send \”${sshpassword}\”
}
@ {
# This never gets executed. Here just in case I ever see the command prompt.
# For testing purposes only.
send_user \”sudo command prompt found\”
}
timeout {
send_user \“sudo timeout was triggered\”
}
eof {
send_user \“sudo eof was triggered\”
}
}
stty echo
interact;” 2>/dev/null
# Here is the output I receive with "testuser1 ALL=(ALL) ALL" in /etc/sudoers.
[testuser1@testserver1 ~]$ ./expect_script
ssh password was triggeredsudo password was triggered
drwxr-xr-x 2 root root 4096 Mar 29 10:07 /root/Desktop
# Here is the output I receive with "testuser1 ALL=(ALL) NOPASSWD: ALL" in /etc/sudoers.
[testuser1@testserver1 ~]$ ./expect_script
ssh password was triggeredsudo eof was triggered[testuser1@testserver1 ~]$
Since sudo is not prompting for a password eof is found and the script exits. That is fine but I would expect to see the same output as above.
# Here is the same code with error redirection (2>/dev/null), "log_user 0", and "stty -echo" removed.
# "testuser1 ALL=(ALL) ALL" in /etc/sudoers
[testuser1@testserver1 ~]$ ./expect_script
testuser1@testserver1's password: ssh password was triggered
[sudo] password for testuser1: sudo password was triggered
drwxr-xr-x 2 root root 4096 Mar 29 10:07 /root/Desktop
# Here is the same code with error redirection (2>/dev/null), "log_user 0", and "stty -echo" removed.
# "testuser1 ALL=(ALL) NOPASSWD: ALL" in /etc/sudoers
[testuser1@testserver1 ~]$ ./expect_script
testuser1@testserver1's password: ssh password was triggered
drwxr-xr-x 2 root root 4096 Mar 29 10:07 /root/Desktop
sudo eof was triggeredspawn_id: spawn id exp4 not open
while executing
"interact"
As you can see I receive the output but other errors as well. I cannot simply grep for what I want because any command can be substitued for "ls -ld /root/Desktop". I won't know what to look for.
I was reading about the expect buffer but not sure if that is my answer.
Any help is appreciated.
i am very new to the expect/autoexpect (have never liked it for p/w as it puts the p/w in plane text) but from what i have been reading the -c " you have for the expect is incomplete you have either no closing " or you have no command. also please use code/code flags this makes life much simpler when reading code. so example:
for the opening code... [ code ] without the spaces and [ / code ] without the spaces to end:
Code:
# echo "Hello world."
# Hello wold.
according to the man page for expect:
Code:
The -c flag prefaces a command to be executed before any in the script.
The command should be quoted to prevent being broken up by the shell.
This option may be used multiple times. Multiple commands may be executed
with a single -c by separating them with semicolons. Commands are executed
in the order they appear. (When using Expectk, this option is specified as
-command.)
like so:
expect -c "strace 4" script.exp
you only have:
Code:
expect –c “
with no command and no closing " to start your script. from what little bash i know this will cause issues as the -c " will continue until it finds an other " to close the command and attempt to run all of them as bash commands. that will be an issue.
from an other forum i just found, this might help
Quote:
You cannot put your expect script coding inside a bash shell script. Bash will not understand expect commands.
You can call the expect utility using "expect -c" command as shown here:
note the last line is a " to close the -c option for expect.
Quote:
.. or you create a separate expect script and invoke it as following:
Code:
(connect.sh)
#!/bin/bash
username="oracle"
hostname="127.0.0.1"
password="mypasword"
./sftp.exp "$username" "$hostname" "$password"
(sftp.exp)
#!/usr/bin/expect
set username [lindex $argv 0]
set hostname [lindex $argv 1]
set password [lindex $argv 2]
spawn sftp $username@$hostname
expect *password:
send "$password\r"
etc.
Not sure if that helps or not, but you might also want to play around with autoexpect to create a file for you. I played around with it to generate a script.exp for ssh with p/w into my iMAC. works well enough without issue. Not sure if those will help, but I hope they do.
Distribution: Slackware 14.1 64-bit, Ubuntu 15.10, Fedora 17, Ubuntu 12 LTS and Ubuntu server 10.04
Posts: 173
Rep:
Since you expect a password prompt and the erroneous entry is the one in which you do not require passwords, I'd expect it to be because no password prompt is shown. Ref: http://stackoverflow.com/questions/1...-exp4-not-open
Small tip: add the extra verbose flag to your shebang to debug scripts (at the top):
Thanks for the tips guys. I think my problem is the linear fashion of my expect statements. After nesting the expect statements and removing the sudo command from the initial ssh session I am getting better results. Basically, I check if ssh failed or not and if successful then I send the sudo command. This way I can control the errors much better. I will post my results probably in a few days if anyone is interested. Thanks for all your help.
I was finally able to get a good working version of my script. A little background - I created a script to get the firmware from a server. I setup the script to walk through an IBM Blade Center and grab the hostnames in the description fields so it can ssh to the server and get the firmware levels. I have included some test cases (embedded after expect command) in case anyone else is trying to do this too. I have included the whole bash function I use in my script. In the function, I only care to retrieve the correct result, if it fails I just want it to return nothing. For anyone copying this you can add send_user commands to get output for the errors if you desire.
## Retrieve Chassis Blade Firmware.
get_chassis_blade_fw() {
export hn_blade=$(snmpwalk -r 10 -Ov -Oq -v $secVersion -u $secName -l $secLevel -a $authProtocol -A $authPassword -x $privProtocol -X $privPassword $hn 1.3.6.1.4.1.2.3.51.2.2.21.5.1.1.5.$1 2>/dev/null | sed 's/"//g')
local chassis_blade_fw=""
local answer=()
export sshUser
export sshPassword
export prompt="${sshUser}@${hn_blade}"
export cmd="/usr/sbin/lsfw ${chassis_blade_options} 2>/dev/null"
if [[ "${chassis_blade_fw}" != "EMPTY" && "${chassis_blade_fw}" != "N/F" ]] ; then
#### Test cases
# Wrong ssh password/username: Returns null.
# Invalid username: Returns null.
# Host invalid/not reachable: Returns null.
# Account locked out: Returns null.
# Account requires password change: Returns null.
# "Your LDAP password will expire in ? days" message: Failed testing. Don't plan to fix.
# Last login message: Filtered by expect.
# "There were ? failed login attempts since the last successful login" message: Filtered by expect.
# Login banner: Filtered by expect.
# ssh_key_exchange failure message:+ (fixed with ssh -q) Returns null.
# ssh keys are setup: (fixed with PubkeyAuthentication=no) Works as expected
# Wrong sudo password: (N/A since same as ssh pwd and ssh will fail) N/A
# No sudo privileges: Returns null
# sudo with NOPASSWD: Works as expected
# Invalid command: Requires 2>/dev/null in $cmd and returns null
####
#### Caveats
# Must use short hostname is AMM blade description field.
####
chassis_blade_fw=$(/usr/bin/expect -c '
set sshUser $env(sshUser)
set sshPassword $env(sshPassword)
set hn $env(hn_blade)
set prompt $env(prompt)
set cmd $env(cmd)
#exp_internal 1
set timeout 2
set send_human {.1 .3 1 .05 2}
match_max 100000
log_user 0
stty -echo
# Return results.
echo "${chassis_blade_fw}"
} # END get_chassis_blade_fw()
You may notice most of the test cases were satisfied by ssh options. One problem with this script I need your help on is how do I wait for all the output after sending a command before it starts matching the expect statements? When I send the sudo command it starts matching right away that is why I have the full_buffer line so it will not match and if the sudo command requires a password it will see the prompt. Without full_buffer it will never match the sudo prompt.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.