Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to terminate a python subprocess launched with shell=True

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().

like image 541
user175259 Avatar asked Jan 25 '11 03:01

user175259


People also ask

How do you stop a subprocess run in Python?

Once you create subprocess with the above command, you can always refer to it using its id attribute as p.id and send a SIGTERM signal to it. Here is the full code to terminate a subprocess created in python. In the above command, we use killpg command to send the terminate signal to all the process groups.

How do you kill a process in Python subprocess?

subprocess. Popen. kill(proc) is exactly the same as proc. kill() FYI.

What is shell true in subprocess Python?

After reading the docs, I came to know that shell=True means executing the code through the shell. So that means in absence, the process is directly started.


2 Answers

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 
like image 136
mouad Avatar answered Sep 20 '22 02:09

mouad


p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) p.kill() 

p.kill() ends up killing the shell process and cmd is still running.

I found a convenient fix this by:

p = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True) 

This will cause cmd to inherit the shell process, instead of having the shell launch a child process, which does not get killed. p.pid will be the id of your cmd process then.

p.kill() should work.

I don't know what effect this will have on your pipe though.

like image 21
Bryant Hansen Avatar answered Sep 20 '22 02:09

Bryant Hansen