1

I am looking at a scenario where I want to run a program / command with sudo as part of a software test. The commands are launched from a Python script based on the subprocess module. I am attempting to avoid having to run the entire test suite with super user privileges.

Let's say for the purpose of this example, it's top. My command starts a few sub-processes of its own and may run into a deadlock. After a timeout, I want to kill it (and its children). The obvious solution appears to be to make my command head of a new session / process group, allowing me to kill it and its children altogether at once. What I can NOT figure out is how to make this work with sudo. In my case, sudo is always password protected without exception and I want keep it this way ... if possible.

  1. Works: setsid top
  2. Works, but does NOT spawn a new process group: sudo setsid top
  3. Problematic - hard to get the root password in in a safe and sound manner: setsid sudo top

I did not manage to make (3) work in a clean way. I messed around with SUDO_ASKPASS.

What surprised me was the fact that (2) actually runs but does NOT give me the desired new process group.

systemd─┬─ ...
        ├─kdeinit5─┬─ ...
        │          └─yakuake─┬─2*[bash]
        │                    ├─bash───sudo───top
        │                    ├─bash───pstree
        ...
  • Ar you looking for subprocess.CREATE_NEW_PROCESS_GROUP? – muru Dec 15 '17 at 11:49
  • @muru My Python process runs with normal user privileges. I know its perfectly possible to make Popen launch a process into a new group - there are in fact multiple ways of doing that. But all of those run into issues associated with scenario 3, i.e. SUDO_ASKPASS, when I try to run something like subprocess.Popen(['sudo', 'top'], start_new_session = True). I was hoping to figure out a way of starting a new session AFTER sudo asks for the password. – s-m-e Dec 15 '17 at 11:57
  • 1
    @s-m-e sudo -b might help (askubuntu.com/a/750423/158442) – muru Dec 15 '17 at 11:58
  • @muru Yep, sudo -b top works, it appears to fire up a new process group. No setsid required. Thanks :) – s-m-e Dec 15 '17 at 12:10
  • @muru subprocess.CREATE_NEW_PROCESS_GROUP is Windows only ... – s-m-e Dec 15 '17 at 16:09
1

Scenario 2 can be fixed like this, without the use of setsid:

sudo -b command

This will create a new process group, directly below the system's init process, including the sudo command.


One word of advise, though: If one starts a process group like this with Python's subprocess.Popen, the resulting object's PID (subprocess.Popen(...).pid) can NOT be used for determining the PGID for eventual use in a pattern like kill -9 -- -{PGID} (it will kill the Python interpreter instead of the newly spawned process group). My workaround (requires psutil):

import os
import psutil
import subprocess

def __get_pid__(cmd_line_list):
    for pid in psutil.pids():
        proc = psutil.Process(pid)
        if cmd_line_list == proc.cmdline():
            return proc.pid
    return None

cmd = ['sudo', '-b', 'command']
cmd_proc = subprocess.Popen(cmd)

print('Wrong PGID: %d' % os.getpgid(cmd_proc.pid))
print('Right PGID: %d' % os.getpgid(__get_pid__(cmd)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.