在 Windows 中终止使用 shell=True 启动的后台进程
Kill background process launched with shell=True in Windows
我正在尝试从 Python 启动 server to score PMML models in Java。计算完成后,我希望能够关闭该服务器(即终止进程)。我在 Windows 10。但是,我发现它比我想象的更令人困惑。
首先我像这样启动服务器:
p = subprocess.Popen('START /B java -jar openscoring-server-executable-1.4.3.jar',
shell=True)
我将其设置为 运行 在后台,这样 CMD window 就不会在用户 运行 执行脚本时出现。为了使这成为可能,我认为 shell=True
参数是必要的。
当我尝试使用此行终止进程时:
subprocess.call("TASKKILL /F /PID {pid} /T".format(pid=p.pid))
进程还在运行ning。事实上, p.pid
returns 这个PID在任务管理器中根本不存在。我在尝试使用 this answer:
中提供的解决方案时确认了这一点
def kill(proc_pid):
process = psutil.Process(proc_pid)
for proc in process.children(recursive=True):
proc.kill()
process.kill()
kill(p.pid)
这个returns异常NoSuchProcess: no process found with pid 5280
。
我可以通过任务管理器看到分配给我要终止的进程的 PID:
但我不知道如何在 Python 中找到 PID 来终止它。我在网站上找到的答案似乎不适用于后台进程 运行ning。
编辑:
我认为如果我能够 运行 使用 shell=False
命令就可以解决这个问题,但由于 START /B
,我不知道该怎么做。这returns一个错误:
p = subprocess.Popen(['START', '/B', 'java', '-jar openscoring-server-executable-1.4.3.jar'])
如果您无法找出正确的 PID,我可能有一个替代解决方案,利用您用来启动该过程的参数。这不是很好,因为您将遍历进程树直到找到命中,但这样它肯定会找到进程。
请记住,如果您有多个进程具有相同的参数 运行,这可能并不总是 return 正确的进程。
def process_get(*args):
"""Returns the process matching ``args``.
Relies on ``args`` matching the argument list of the process to find.
Args:
*args: process arguments, e.g. ["java", "-jar", "somejar.jar"]
Returns:
:obj:`process`
"""
import psutil
for process in psutil.process_iter():
try:
if process.cmdline() == args:
return process
except psutil.AccessDenied:
pass
return None
您可以在此处搜索您的应用并关闭。
import psutil
import os
ls = []
for p in psutil.process_iter():
try:
name = p.name()
cmdline = p.cmdline()
exe = p.exe()
pid = p.pid
except (psutil.AccessDenied, psutil.ZombieProcess):
continue
except psutil.NoSuchProcess:
continue
此行不起作用,因为您需要提供所有参数和准确的字符串。
if process.cmdline() == args:
我将其更改为包括一些字符串和部分字符串:
def process_get(*args):
"""Returns the process matching ``args``.
Relies on ``args`` matching the argument list of the process to find.
Args:
*args: process arguments, e.g. ["java", "jar", "partialjarname"]
Returns:
:obj:`process`
"""
import psutil
for process in psutil.process_iter():
try:
if all(x in " ".join(process.cmdline()) for x in args):
return process
except psutil.AccessDenied:
pass
return None
我正在尝试从 Python 启动 server to score PMML models in Java。计算完成后,我希望能够关闭该服务器(即终止进程)。我在 Windows 10。但是,我发现它比我想象的更令人困惑。
首先我像这样启动服务器:
p = subprocess.Popen('START /B java -jar openscoring-server-executable-1.4.3.jar',
shell=True)
我将其设置为 运行 在后台,这样 CMD window 就不会在用户 运行 执行脚本时出现。为了使这成为可能,我认为 shell=True
参数是必要的。
当我尝试使用此行终止进程时:
subprocess.call("TASKKILL /F /PID {pid} /T".format(pid=p.pid))
进程还在运行ning。事实上, p.pid
returns 这个PID在任务管理器中根本不存在。我在尝试使用 this answer:
def kill(proc_pid):
process = psutil.Process(proc_pid)
for proc in process.children(recursive=True):
proc.kill()
process.kill()
kill(p.pid)
这个returns异常NoSuchProcess: no process found with pid 5280
。
我可以通过任务管理器看到分配给我要终止的进程的 PID:
但我不知道如何在 Python 中找到 PID 来终止它。我在网站上找到的答案似乎不适用于后台进程 运行ning。
编辑:
我认为如果我能够 运行 使用 shell=False
命令就可以解决这个问题,但由于 START /B
,我不知道该怎么做。这returns一个错误:
p = subprocess.Popen(['START', '/B', 'java', '-jar openscoring-server-executable-1.4.3.jar'])
如果您无法找出正确的 PID,我可能有一个替代解决方案,利用您用来启动该过程的参数。这不是很好,因为您将遍历进程树直到找到命中,但这样它肯定会找到进程。
请记住,如果您有多个进程具有相同的参数 运行,这可能并不总是 return 正确的进程。
def process_get(*args):
"""Returns the process matching ``args``.
Relies on ``args`` matching the argument list of the process to find.
Args:
*args: process arguments, e.g. ["java", "-jar", "somejar.jar"]
Returns:
:obj:`process`
"""
import psutil
for process in psutil.process_iter():
try:
if process.cmdline() == args:
return process
except psutil.AccessDenied:
pass
return None
您可以在此处搜索您的应用并关闭。
import psutil
import os
ls = []
for p in psutil.process_iter():
try:
name = p.name()
cmdline = p.cmdline()
exe = p.exe()
pid = p.pid
except (psutil.AccessDenied, psutil.ZombieProcess):
continue
except psutil.NoSuchProcess:
continue
此行不起作用,因为您需要提供所有参数和准确的字符串。
if process.cmdline() == args:
我将其更改为包括一些字符串和部分字符串:
def process_get(*args):
"""Returns the process matching ``args``.
Relies on ``args`` matching the argument list of the process to find.
Args:
*args: process arguments, e.g. ["java", "jar", "partialjarname"]
Returns:
:obj:`process`
"""
import psutil
for process in psutil.process_iter():
try:
if all(x in " ".join(process.cmdline()) for x in args):
return process
except psutil.AccessDenied:
pass
return None