You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:15:46