How to terminate a python subprocess launched with shell=True

kill-process, linux, python, subprocess

Solution

Use a process group so as to enable sending a signal to all the process in the groups. For that, you should attach a session id to the parent process of the spawned/child processes, which is a shell in your case. This will make it the group leader of the processes. So now, when a signal is sent to the process group leader, it's transmitted to all of the child processes of this group.

Here's the code:

import os
import signal
import subprocess

# The os.setsid() is passed in the argument preexec_fn so
# it's run after the fork() and before  exec() to run the shell.
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
                       shell=True, preexec_fn=os.setsid) 

os.killpg(os.getpgid(pro.pid), signal.SIGTERM)  # Send the signal to all the process groups

Problem

I'm launching a subprocess with the following command: ``` p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) ``` However, when I try to kill using: ``` p.terminate() ``` or ``` p.kill() ``` The command keeps running in the background, so I was wondering how can I actually terminate the process. Note that when I run the command with: ``` p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) ``` It does terminate successfully when issuing the `p.terminate()`.

Original source

Related problems