Search code examples
pythonif-statementsubprocesspopenpid

Process execution check and getting PID in Python


I need to run a bash command in the background but then need to kill(os.kill()) it later. I also want to make Sure the command runs I have this to make sure the command runs.

if subprocess.Popen("tcpdump -i eth0 -XX -w /tmp/tmp.cap &", shell=True).wait() == 0:

I'm not sure on how to change this so i can use Popen.pid to get the pid while still being able to check if execution was successful. Any help would be appreciated. Thanks.


Solution

  • To start a subprocess, wait some time and kill it, and check that its exit status is zero:

    import shlex
    from subprocess import Popen
    from threading import Timer
    
    def kill(process):
        try:
            process.kill()
        except OSError: 
            pass # ignore
    
    p = Popen(shlex.split("tcpdump -i eth0 -XX -w /tmp/tmp.cat"))
    t = Timer(10, kill, [p]) # run kill in 10 seconds
    t.start()
    returncode = p.wait()
    t.cancel()
    if returncode != 0:
       # ...
    

    Or you could implement the timeout yourself:

    import shlex
    from subprocess import Popen
    from time import sleep, time as timer # use time.monotonic instead
    
    p = Popen(shlex.split("tcpdump -i eth0 -XX -w /tmp/tmp.cat"))
    
    deadline = timer() + 10 # kill in 10 seconds if not complete
    while timer() < deadline:
        if p.poll() is not None: # process has finished
            break 
        sleep(1) # sleep a second
    else: # timeout happened
        try:
            p.kill()
        except OSError:
            pass
    
    if p.wait() != 0:
       # ...
    

    It assumes sleep uses similar clock as timer.

    threading.Timer variant allows your code to continue as soon as the subprocess exits.