I'm running a Python script from my NGINX server that runs this command
subprocess.call(["sh", "/runscript.sh", arg1, arg2, arg3], shell=False)
Problem is that when my server kill the script execution, the subprocess runned can't stop, just run forever.
That's a huge problem.
Already tried to change shell=True/shell=False.
EDIT
I've implemented the code inside the sh script inside the python script.
So now process start directly from subprocess.call.
There is a ways to save the PID of processes started from subprocess.call and end when task does not have input?
First, you can:
import os
os.system("tasklist > task.temp")
with open("task.temp", "r") as f:
print(f.read())
task = input("Enter process: ")
os.system("taskkill /f /im "+task)
After you find out which task name belongs to runscript.sh, you can replace it to:
import os
os.system("taskkill /f /im "+task)
Where task is the name of the process you want to terminate.
Related
Hello I just wont to kill a process without killing current process suppose that i have a python code which write a string in txt file e.g
import os
while True:
with open('input.txt' , 'r') as re:
all_data = re.read()
if all_data == 'pause':
os.system('kill.bat')
else:
print("\nContinue\n")
here it will read input.txt and if it is equal to pause then it will run kill.bat here i would like to restart this code for doing this i will write another script kill.bat which restart this code but the problem is it is not restarting because it was killing kill.bat file but i wont to kill only python terminal and restart it how can i do it here is kill.bat file code
taskkill /IM cmd.exe
python main.py
main.py is my python file
Nice try #Pryanshu
You're doing it right. The problem with your current approach is python and the batch script will be under same process and get's killed at the same time.
So just change the approach a bit
here's the gist:
python
get current process id
while loop
read file
if matches condition
call kill.bat and pass this python process ID as separate process
batch
get first parameter (which is the python process to kill)
kill the process via taskkill
start the python script as seprate process
exit
Helpers
get current process ID - pid = os.getpid()
pass id to batch script - os.system("kill.bat %s" % pid)
batch script get arguments - %1
this %1 will contain the first argument passed.
by default %* will contain all the arguments passed to the script.
python start program as
separate process - use subprocess python package
cmd start program as
separate process - use Start command
kill process via taskkill - taskkill /F /PID <pid>
replace <pid> with your argument
I know you can handle the code part. You'll have to make use of the Helpers and combine them to do the task. Lemme know the output.
If you have any question do comment. I'll try to reply ASAP
Cheers
I am trying to run a Python script from another Python script, and getting its pid so I can kill it later.
I tried subprocess.Popen() with argument shell=True', but thepidattribute returns thepid` of the parent script, so when I try to kill the subprocess, it kills the parent.
Here is my code:
proc = subprocess.Popen(" python ./script.py", shell=True)
pid_ = proc.pid
.
.
.
# later in my code
os.system('kill -9 %s'%pid_)
#IT KILLS THE PARENT :(
shell=True starts a new shell process. proc.pid is the pid of that shell process. kill -9 kills the shell process making the grandchild python process into an orphan.
If the grandchild python script can spawn its own child processes and you want to kill the whole process tree then see How to terminate a python subprocess launched with shell=True:
#!/usr/bin/env python
import os
import signal
import subprocess
proc = subprocess.Popen("python script.py", shell=True, preexec_fn=os.setsid)
# ...
os.killpg(proc.pid, signal.SIGTERM)
If script.py does not spawn any processes then use #icktoofay suggestion: drop shell=True, use a list argument, and call proc.terminate() or proc.kill() -- the latter always works eventually:
#!/usr/bin/env python
import subprocess
proc = subprocess.Popen(["python", "script.py"])
# ...
proc.terminate()
If you want to run your parent script from a different directory; you might need get_script_dir() function.
Consider importing the python module and running its functions, using its object (perhaps via multiprocessing) instead of running it as a script. Here's code example that demonstrates get_script_dir() and multiprocessing usage.
So run it directly without a shell:
proc = subprocess.Popen(['python', './script.py'])
By the way, you may want to consider changing the hardcoded 'python' to sys.executable. Also, you can use proc.kill() to kill the process rather than extracting the PID and using that; furthermore, even if you did need to kill by PID, you could use os.kill to kill the process rather than spawning another command.
I have a simple script that calls another python script as a subprocess. I can confirm the subprocess is started and I can grab its PID.
When I attempt to terminate the subprocess (in win), I get the SUCCESS message against the correct PID, but Windows task manager shows the 2nd python.exe process to still be running.
Any suggestions to accomplish this task in Win? I'll be extending this to also work in OSX and Linux eventually:
Simplified:
#!/usr/bin/env python
import os, sys
import subprocess
from subprocess import Popen, PIPE, STDOUT, check_call
pyTivoPath="c:\pyTivo\pyTivo.py"
print "\nmyPID: %d" % os.getpid()
## Start pyTivo ##
py_process = subprocess.Popen(pyTivoPath, shell=True, stdout=PIPE, stderr=subprocess.STDOUT)
print "newPID: %s" % py_process.pid
## Terminate pyTivo ##
#py_process.terminate() - for nonWin (?)
py_kill = subprocess.Popen("TASKKILL /PID "+ str(py_process.pid) + " /f")
raw_input("\nPress Enter to continue...")
Note: Python2.7 required, psutils not available
In my implementation, the following actually creates TWO processes in Windows ("cmd.exe" and "python.exe").
py_process = subprocess.Popen(pyTivoPath, shell=True, stdout=PIPE, stderr=subprocess.STDOUT)
Noticing the "python.exe" process is a child of the "cmd.exe" process, I added the "/T" (tree kill) switch to my TASKKILL:
py_kill = subprocess.Popen("TASKKILL /PID "+ str(py_process.pid) + " /f /t")
This results in the desired effect to effectively KILL the python subprocess.
Two processes are created because you call Popen with shell=True. It looks like the only reason you need to use a shell is so you make use of the file association with the interpreter. To resolve your issue you could also try:
from subprocess Popen, PIPE, STDOUT
pyTivoPath = "c:\pyTivo\pyTivo.py"
cmd = r'c:\Python27\python.exe "{}"'.format(pyTivoPath)
# start process
py_process = Popen(cmd, stdout=PIPE, stderr=STDOUT)
# kill process
py_process.terminate()
Use the /F (Force) switch on the TASKKILL command. Lots of windows commands do not has useful return values. Don't recall if TASKKILL returns has a useful value.
Sorry, overlooked your /F
You could try calling the win32 api directly.
import win32api
win32api.TerminateProcess(int(process._handle), -1)
Found the ActiveState page for this. Documents a number of kill methods, including the Win32 approach above.
There are also a number of reasons why Windows will not allow you to terminate a process. Common reasons are permissions and buggy drivers that have pending I/O requests that don't response to the kill signal properly.
There are some programs, e.g. ProcessHacker, that are more enthusiastic about killing processes, but I don't know the technical details for certain, though I suspect forced closing of open file handles etc. and then calling Terminate are involved.
You can have similar issues on Linux, i.e., no permission to kill process or the process is ignoring the kill signal. Easier to resolve on Linux though, if kill -9 does not work, it can't be killed and it is a rarer condition because you have to ignore signal 9 explicitly in your code.
0) You could use TASKKILL /T to kill CMD and the Python interpreter.
1) If you change your process creation to create the python process directly (instead of invoking the .py and relying on cmd to launch) with the script name as command argument you will get the PID you expect when you create the process.
2) You could use TASKKILL /IM to kill the process by name, but the name will be the python interpreter and it could kill unintended processes.
I'm using Python 2.6. Sometimes there become several instances of a certain process open, and that process causes some problems in itself. I want to be able to programatically detect that there are multiple instances of that process and to kill them.
For example, maybe in some cases there are 50 instances of make.exe open. I want to be able to tell that there are 20 instances open, and to kill them all. How is this accomplished?
I would think you could just use taskkill and the Python os.system()
import os
os.system("taskkill /im make.exe")
Note: I would just note you might have to fully qualify the taskkill path. I am using a Linux box so I can't test...
Yes,You can do it
import os
os.system("taskkill /f /im Your_Process_Name.exe")
/f : Specifies that process(es) be forcefully terminated.
/im (ImageName ): Specifies the image name of the process to be
terminated.
For more info regarding TaskKill
There is a nice cross-platform python utility psutil that exposes a kill() routine on a processes that can be listed with psutil.process_iter().
There is already an example in the other thread: https://stackoverflow.com/a/4230226/4571444
You can use the TerminateProcess of the win32 api to kill a process. See the following example : http://code.activestate.com/recipes/347462-terminating-a-subprocess-on-windows/
You need to give it a process handle. If the process is started from your code, the process handle is returned by the CreateProcess or popen.
If the process was started by something else, you need to get this handle you can use EnumProcess or WMI to retrieve it.
How about this, I tested it with ActiveState Python 2.7:
import sys, traceback, os
def pkill (process_name):
try:
killed = os.system('tskill ' + process_name)
except Exception, e:
killed = 0
return killed
call it with:
pkill("program_name")
I think the code is like this will work:
import os
def terminate(ProcessName):
os.system('taskkill /IM "' + ProcessName + '" /F')
terminate('chrome.exe')
Is there a way that python can close a windows application (example: Firefox) ?
I know how to start an app, but now I need to know how to close one.
# I have used subprocess comands for a while
# this program will try to close a firefox window every ten secounds
import subprocess
import time
# creating a forever loop
while 1 :
subprocess.call("TASKKILL /F /IM firefox.exe", shell=True)
time.sleep(10)
If you're using Popen, you should be able to terminate the app using either send_signal(SIGTERM) or terminate().
See docs here.
in windows you could use taskkill within subprocess.call:
subprocess.call(["taskkill","/F","/IM","firefox.exe"])
/F forces process termination. Omitting it only asks firefox to close, which can work if the app is responsive.
Cleaner/more portable solution with psutil (well, for Linux you have to drop the .exe part or use .startwith("firefox"):
import psutil,os
for pid in (process.pid for process in psutil.process_iter() if process.name()=="firefox.exe"):
os.kill(pid)
that will kill all processes named firefox.exe
By the way os.kill(pid) is "overkill" (no pun intended). process has a kill() method, so:
for process in (process for process in psutil.process_iter() if process.name()=="firefox.exe"):
process.kill()
You want probably use os.kill http://docs.python.org/library/os.html#os.kill
In order to kill a python tk window named MyappWindow under MS Windows:
from os import system
system('taskkill /F /FI "WINDOWTITLE eq MyappWindow" ')
stars maybe used as wildcard:
from os import system
system('taskkill /F /FI "WINDOWTITLE eq MyappWind*" ')
Please, refer to "taskkill /?" for additional options.
On OS X:
Create a shell script and put:
killall Application
Replace Application with a running app of your choice.
In the same directory as this shell script, make a python file.
In the python file, put these two lines of code:
from subprocess import Popen
Popen('sh shell.sh', shell=True)
Replace shell.sh with the name of your created shell script.
An app(a running process) can be closed by it's name using it's PID(Process ID) and by using psutil module. Install it in cmd using the command:
pip install psutil
After installing, run the code given below in any .py file:
import psutil
def close_app(app_name):
running_apps=psutil.process_iter(['pid','name']) #returns names of running processes
found=False
for app in running_apps:
sys_app=app.info.get('name').split('.')[0].lower()
if sys_app in app_name.split() or app_name in sys_app:
pid=app.info.get('pid') #returns PID of the given app if found running
try: #deleting the app if asked app is running.(It raises error for some windows apps)
app_pid = psutil.Process(pid)
app_pid.terminate()
found=True
except: pass
else: pass
if not found:
print(app_name+" not found running")
else:
print(app_name+'('+sys_app+')'+' closed')
close_app('chrome')
After running the code above you may see the following output if google chrome was running:
>>> chrome(xyz) closed
Feel free to comment in case of any error