SU and Run Command Using Expect
I want to su to another user, using expect, and then run a graphical program as that user. I am using kcalc to test with:
#!/usr/bin/expect
set timeout 20
spawn su dummy
expect "Password:"
send "PASS\r";
send "kcalc\r"
I also tried eliminating the last line and changing the su to 'su dummy -c kcalc', but that didn't work either. I appreciate any help.
Instead of leaving account passwords sitting around the file system, why not just create a sudo command to do specifically this, and grant it with the NOPASSWD option?
I was just doing this today using spawn SSH sessions here are some bits of the code I wrote not sure if it will help:
echo "Type the account you wish to use to issue the command, followed by [ENTER]: "
read account
read -s -p "Password: " password
echo "Type the command you wish to execute, followed by [ENTER]: "
read command
echo "Type the hostname you want to connect to, followed by [ENTER]: "
read hostname
switchToSudo="sudo su"
shortenedHost=`echo $hostname|cut -d. -f 1`
accountSwitched="root@$shortenedHost:/home/$account#"
VAR=$(expect -c "
expect \"*~$\"
send \"$switchToSudo\r\"
expect \"*?assword*\"
send \"$password\r\"
spawn ssh $account@$hostname
expect "*?assword:*"
send \"$password\r\"
expect \"*~$\"
send \"$switchToSudo\r\"
expect ""
send \"$command\r\n\"
send "logoff"
")
echo "=============="
echo "$VAR"
exit
You have a couple of options here.
1) As MrTuttle stated, adding your user to sudoers with NOPASSWD is preffered. This will prevent needing to store a clear-text root password /etc/sudoers
yourUser ALL=(OtherUser) NOPASSWD:/path/to/kcalc
will allow you to
$ sudo -u OtherUser kcalc
with out being prompted for a password.
2) Your current script.
Your current script should work, keep in mind, that not every system and prompt capitalizes "Password:" or leaves a space at the end. I find that "assword" is a better string to test with. The other thing to note is that su is asking for the ROOT password, not user dummy. If you don't have the root password, you will need to login as dummy instead (usualy ssh -l dummy localhost)
for some debugging steps, you can try multiple statements during the password phase of your expect. I find it useful to test and report for timeout and eof while developing scripts.
You might want to try this to help see where your script is ending
expect {
-re "(.*)assword:" { sleep 1; send -- "password\r" }
timeout { puts "un-able to login: timeout\n"; return }
eof { puts "Closed\n" ; return }
}