Running sudo (provide password) with exec.Command


(Rob Marshall) #1

Hi,

I would like to be able to run commands on the local host (not SSH) but how should I handle a password prompt if the command uses sudo on Linux?

Thanks,

Rob


(Johan Dahl) #2

Hi. It is better to run the whole application with sudo or configure sudo so you can run some commands without password.


(Rob Marshall) #3

Hi,

I don’t have control over the sudoers file so I can’t change my access to allow running the commands without a password.

As far as running the entire command with sudo, I suppose I could modify the owner/group of any files created by the application. But it would be “cleaner” to be able to reply to the prompt for the sudo password when, or if, it comes up.

Since it works when using SSH (found an example that starts a “go func” that reads the output and sends the password if it sees the prompt), perhaps the best answer is to SSH to the localhost.

Rob


(Johan Dahl) #4
package main

import (
	"fmt"
	"os"
	"os/exec"
)

func main() {
	cmd := exec.Command("sudo", "ls")
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout

	err := cmd.Run()
	if err != nil {
		fmt.Println(err)
	}
}

This calls command with sudo and connects sudo. stderr, stdout and stdin to the running applications stdin etc. sudo uses stdin and stderr so if you want to read stdout from the command you could do like this:

package main

import (
	"fmt"
	"os"
	"os/exec"
)

func main() {
	cmd := exec.Command("sudo", "ls")
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin

	out, err := cmd.Output()
	if err != nil {
		fmt.Println("Err", err)
	} else {
		fmt.Println("OUT:", string(out))
	}
}

(Rob Marshall) #5

The normal way Linux prompts for the sudo password is to bypass stdout/stderr/stdin and write/read directly from the tty. However if you add the ‘-S’ argument then it will print the prompt to stderr. So what I was able to do was the do a Peek() on stderr and if there is something there, I collect it to see if it’s a prompt. If it is, then I can write the sudo password to stdin and all is well.

Rob


(Eric Lindblad) #6

Could you from your code call an external shell script and attend to sudo (and the password for sudo) both from within that script, obviously with certain special permissions on that shell script?


(Rob Marshall) #7

Hi,

I can use SSH which always seems to put the prompt on the output stream and I can then check for it, or modify the ‘sudo’ calls to always use -S and check on stderr. If I put them in a shell script I run into the same issues, i.e. I still have to use -S in order to ensure that the prompt is sent to stderr rather than the tty. And then the shell script would have to handle it which is potentially less efficient than handling in the original Go executable, i.e. once in Go or, potentially, multiple scripts for multiple ‘sudo’ commands.

Rob