views:

3045

answers:

3

Heyas

So I'm trying to get a process to be run as a super user from within a python script using subprocess. In the ipython shell something like

proc = subprocess.Popen('sudo apach2ctl restart', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

works fine, but as soon as I stick it into a script I start getting: sudo: apach2ctl: command not found I would guess is due to the way sudo handles environments on ubuntu. (I've also tried sudo -E apche2ctl restart and sudo env path=$PATH apache2ctl restart with no avail)

So my question is basically, if I want to run apache2ctl restart as super user that prompts the user for the super user password when required, how should I go about doing this? I have no intention of storing passwords in the script.

Thanks!

Edit: I've tried passing in the commands as both a string and tokenized into a list. In the python interpreter, with a string I'll get the password prompt properly (still doesnt work in a python script as in my original problem), a list just gives the help screen for sudo.

Ahhh ok, it's a combination of the two. So what I gather is that while Popen will work with some commands just as strings when shell=True, it takes Popen(['sudo','/usr/sbin/apache2ctl','restart']) to get sudo to work.

Another note, no shell=True.

Thanks!

+2  A: 

You have to use Popen like this:

cmd = ['sudo', 'apache2ctl', 'restart']
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

It expects a list.

Harley
Read http://docs.python.org/library/subprocess.html There is a difference between a string and sequence args when shell=True.
J.F. Sebastian
Ah I see, I've never used it like that before.
Harley
+3  A: 

Try giving the full path to apache2ctl.

dwc
I think you've hit on it. Running a script from the interpreter inherits $PATH from the interactive shell which is running it. When run as a script, however, $PATH is inherited from a NON-interactive shell and may well not be the same. It's best to always specify full paths when using popen().
Ben Blank
Yeah - whenever you reference binaries from scripts, you can't rely on $PATH being there for you. By the way, "apch2ctl" is misspelled. ;)
ojrac
+1  A: 

Try:

subprocess.call(['sudo', 'apach2ctl', 'restart'])

The subprocess needs to access the real stdin/out/err for it to be able to prompt you, and read in your password. If you set them up as pipes, you need to feed the password into that pipe yourself.

If you don't define them, then it grabs sys.stdout, etc...

Mike Boers