LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This 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

Reply
 
Search this Thread
Old 04-27-2013, 05:04 PM   #1
linuxguru1
LQ Newbie
 
Registered: Apr 2013
Location: Maryland
Distribution: RHEL
Posts: 7

Rep: Reputation: Disabled
expect command ssh sudo error


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.

hn="testserver1"
sshUser="testuser1"
sshPassword="testpassword1"


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.
 
Old 04-28-2013, 10:23 AM   #2
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora
Posts: 2,540

Rep: Reputation: 462Reputation: 462Reputation: 462Reputation: 462Reputation: 462
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:

Code:
expect -c "
spawn sftp $username@$hostname
expect \"password:\"
send \"$password\r\"
"
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.

Last edited by lleb; 04-28-2013 at 10:26 AM.
 
Old 04-28-2013, 10:27 AM   #3
Sigg3.net
Member
 
Registered: Mar 2008
Location: Oslo, Norway
Distribution: Fedora 17, Ubuntu 12 LTS and Ubuntu server 10.04
Posts: 161

Rep: Reputation: 22
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):
Code:
#!/bin/bash -xv
Then you can run the script and see what happens
 
1 members found this post helpful.
Old 04-29-2013, 07:13 AM   #4
linuxguru1
LQ Newbie
 
Registered: Apr 2013
Location: Maryland
Distribution: RHEL
Posts: 7

Original Poster
Rep: Reputation: Disabled
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.
 
Old 04-29-2013, 08:09 AM   #5
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora
Posts: 2,540

Rep: Reputation: 462Reputation: 462Reputation: 462Reputation: 462Reputation: 462
glad to help, yes i would be interested in your final script.
 
Old 05-07-2013, 03:57 PM   #6
linuxguru1
LQ Newbie
 
Registered: Apr 2013
Location: Maryland
Distribution: RHEL
Posts: 7

Original Poster
Rep: Reputation: Disabled
Final script

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"

# Check for conditions.
[[ "${hn_blade}" = '(No name)' ]] && chassis_blade_fw="EMPTY"
[[ "${hn_blade:0:5}" = "Error" ]] && chassis_blade_fw="N/F"
[[ "${hn_blade:0:7}" = "timeout" ]] && chassis_blade_fw="N/F"
[[ "${hn_blade:0:8}" = "snmpwalk" ]] && chassis_blade_fw="N/F"
[[ "${hn_blade:0:14}" = 'No Such Object' ]] && chassis_blade_fw="N/F"
[[ "${hn_blade:0:16}" = 'No Such Instance' ]] && chassis_blade_fw="N/F"
[[ -z "${hn_blade}" ]] && chassis_blade_fw="N/F"

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

spawn -noecho ssh -q -o PubkeyAuthentication=no -o NumberOfPasswordPrompts=1 -o StrictHostKeyChecking=no -o ConnectTimeout=3 $hn -l $sshUser -t

expect {
default { exit 1 }
-nocase password: { send "$sshPassword\r" }
}

expect {
default { exit 1 }
-re ${prompt} {
send "/usr/bin/sudo $cmd\r"
expect full_buffer { exp_continue } ; # Force all output before continuing.
}
-re (expired|change) { exit 1 }
}

expect {
default { exit 1 }

# Sudo requires password.
"password for $sshUser: " {
send "$sshPassword\r"

expect -indices -re $prompt
set sudo_out [string range $expect_out(buffer) 0 [expr $expect_out(0,start) -1]] ; # Retrive only expected output.

# Trim garbage output.
set sudo_out [string trimleft "$sudo_out" " \r\n"]
set sudo_out [string trimright "$sudo_out" "\r\n\u001b\]0\;${prompt}:~\u0007\["]
send_user [string trimright "$sudo_out" "\r\n\u001b\]0\;"]
exit
}

# Sudo does not require a password (from sudo grace period or NOPASSWD).
-re ".*${cmd}(.*)${prompt}" {
set sudo_out $expect_out(1,string)

# Trim garbage output.
set sudo_out [string trimleft "$sudo_out" " \r\n"]
set sudo_out [string trimright "$sudo_out" "\r\n\u001b\]0\;${prompt}:~\u0007\["]
send_user [string trimright "$sudo_out" "\r\n\u001b\]0\;"]
exit
}
}

stty echo
interact;' 2>/dev/null)
fi

# Check for conditions.
[[ -z "${chassis_blade_fw}" ]] && chassis_blade_fw="${hn_blade} (N/R)"

# 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.

Thanks.
 
Old 05-07-2013, 03:59 PM   #7
linuxguru1
LQ Newbie
 
Registered: Apr 2013
Location: Maryland
Distribution: RHEL
Posts: 7

Original Poster
Rep: Reputation: Disabled
Can someone tell me how to keep the formatting in the code? It looks horrible after I hit send.

Last edited by linuxguru1; 05-07-2013 at 04:00 PM. Reason: spelling
 
Old 05-07-2013, 04:40 PM   #8
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora
Posts: 2,540

Rep: Reputation: 462Reputation: 462Reputation: 462Reputation: 462Reputation: 462
use [ code ] and [ / code ] without the spaces and that will do the trick.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Error while running the command : sudo apxs -i -c mod_lisp2.c barun mukhopadhyay Linux - Server 14 03-14-2013 07:21 AM
[SOLVED] echo "${SUDO_PASSWORD}" | ssh sudo -S command r0tty Linux - Security 7 01-18-2013 06:26 AM
how to expect with sudo? rabbit2345 Programming 4 04-28-2008 07:58 PM
How to use EXPECT command to scp or ssh? thefountainhead100 Linux - Software 6 03-28-2008 06:41 PM
PHP-CLI, expect, dump and sudo problem gw1500se Programming 2 03-05-2008 07:43 PM


All times are GMT -5. The time now is 07:22 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration