Python中subprocess.Popen启动adb后无法杀死进程的技术咨询
这个问题确实很常见——adb的daemon启动机制就是这样:当daemon未运行时,你启动的第一个adb进程会负责拉起daemon,完成任务后就自行退出,导致你通过subprocess.Popen拿到的PID根本是个已经终止的进程,自然没法用来杀掉真正在后台运行的daemon。给你几个靠谱的解决办法,按推荐程度排序:
1. 直接用adb自带的
kill-server命令(最推荐) adb本身就提供了专门终止daemon的标准命令,不管这个daemon是怎么启动的(手动、subprocess或者其他方式),只要运行它就能干净利落地杀掉后台的adb daemon,完全不用纠结PID的问题:
import subprocess # 执行你的adb get-state命令 proc = subprocess.Popen(["adb", "get-state"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() # 之后要终止adb daemon的话,直接调用kill-server subprocess.run(["adb", "kill-server"], check=True)
这是adb官方设计的操作方式,稳定性和可靠性拉满,优先用这个就对了。
2. 通过进程特征定位并终止adb daemon
如果你不想依赖adb自带的命令,也可以通过进程的特征来定位daemon:
- adb daemon默认会监听5037端口
- 进程名通常就是
adb(Windows系统下是adb.exe)
可以用psutil库来实现这个逻辑,先安装psutil:pip install psutil,然后参考下面的代码:
import psutil import subprocess def kill_adb_daemon(): for proc in psutil.process_iter(['pid', 'name', 'cmdline']): try: # 检查进程名或命令行是否包含adb if 'adb' in proc.name().lower() or any('adb' in part.lower() for part in proc.cmdline()): # 验证是否是监听5037端口的daemon进程 for conn in proc.connections(): if conn.laddr.port == 5037: proc.kill() print(f"Killed adb daemon with PID: {proc.pid}") return except (psutil.NoSuchProcess, psutil.AccessDenied): # 进程已退出或无权限访问,直接跳过 continue # 执行adb命令 proc = subprocess.Popen(["adb", "get-state"]) proc.wait() # 杀掉adb daemon kill_adb_daemon()
这个方法适合需要更精细控制进程的场景,比如你只想终止特定的adb进程(不过一般情况下adb daemon只会有一个)。
3. 跟踪初始adb进程的子进程(适合特殊场景)
如果你一定要通过跟踪subprocess.Popen启动的进程来找到daemon,可以尝试在初始进程退出前捕获它的子进程——因为初始adb进程拉起daemon时会fork出一个子进程,这个子进程就是真正的后台daemon:
import psutil import subprocess import time # 启动adb get-state命令 proc = subprocess.Popen(["adb", "get-state"]) # 立即尝试获取初始进程的子进程(要快,因为初始进程很快会退出) daemon_pid = None try: adb_parent_proc = psutil.Process(proc.pid) # 获取所有子进程,adb daemon应该是唯一的子进程 child_procs = adb_parent_proc.children(recursive=True) if child_procs: daemon_pid = child_procs[0].pid print(f"Captured adb daemon PID: {daemon_pid}") except psutil.NoSuchProcess: # 初始进程已经退出,只能换其他方法找daemon了 pass # 等待初始adb进程执行完成 proc.wait() # 如果成功捕获到daemon的PID,就尝试杀掉它 if daemon_pid: try: daemon_proc = psutil.Process(daemon_pid) daemon_proc.kill() print(f"Killed adb daemon with PID: {daemon_pid}") except psutil.NoSuchProcess: print("Daemon process has already exited")
这个方法的缺点是时机很关键,如果初始进程退出太快,可能会错过捕获子进程的机会,所以稳定性不如前两个方案,只适合特殊需求的场景。
内容的提问来源于stack exchange,提问作者Azeeb
相关产品推荐
相关产品推荐

