1. 项目概述:为什么要在WSL里折腾ADB?
如果你是一个在Windows上搞Android开发或者深度玩机的朋友,肯定对ADB不陌生。这个命令行工具是连接电脑和Android设备的生命线,从安装应用、传输文件到抓取日志、刷机,几乎无所不能。但很多时候,我们主力开发环境又是在Linux下,无论是脚本的兼容性、包管理的便捷性,还是某些Linux独有的工具链,都让人欲罢不能。于是,一个很自然的需求就产生了:能不能在我Windows的WSL(Windows Subsystem for Linux)里,也装上ADB,让我既能享受Windows的便利,又能无缝使用Linux环境下的开发流程?
这个需求听起来简单,实操起来却有不少门道。直接在WSL里apt install android-tools-adb装上,你会发现它很可能识别不了你插在Windows主机上的Android设备。这是因为WSL和Windows主机在硬件访问上是隔离的,WSL里的Linux内核并不能直接接管USB设备。所以,这不是一个简单的安装问题,而是一个涉及“跨系统调试桥接”的系统工程。今天,我就来详细拆解一下在WSL(以Ubuntu发行版为例)中完美安装并配置ADB的完整方案,让你彻底告别“设备未找到”的烦恼,实现高效的双系统协同调试。
2. 核心思路与方案选型:穿越“次元壁”的几种方法
要在WSL里使用ADB控制连接在Windows主机上的Android设备,核心矛盾在于:设备在Windows的USB总线里,而ADB命令在WSL的Linux用户空间里。解决这个矛盾,本质上就是要在两个系统之间建立一条通信通道,让Linux里的ADB服务能“看到”并管理Windows那边的设备。目前主流有三大类方案,各有优劣。
2.1 方案一:TCP/IP网络连接(最推荐、最通用)
这是目前最稳定、兼容性最好的方案。其原理是让Windows主机上的ADB服务以网络服务的形式运行,并监听一个TCP端口(默认是5037)。然后,WSL里的ADB客户端通过TCP/IP网络连接到这个端口,从而间接控制设备。整个数据流是:WSL-adb-client -> TCP/IP -> Windows-adb-server -> USB -> Android设备。
优点:
- 无需额外驱动或内核模块:完全在用户空间实现,最干净。
- 跨网络可用:一旦设置好,甚至可以通过网络连接同一局域网内其他电脑上的设备(需配置)。
- 稳定可靠:经过大量开发者验证,是Google官方ADB支持的标准工作模式之一。
- 便于脚本化:连接建立后,后续操作与本地USB连接无异。
缺点:
- 需要额外的初始化步骤:必须先确保Windows端的ADB服务已启动并监听,且WSL端需要手动连接。
- 如果Windows防火墙设置不当,可能会阻止连接。
2.2 方案二:使用usbipd-win工具映射USB设备(最“原生”)
这个方案更底层一些。它利用Linux内核的usbip(USB over IP)功能,配合Windows上的开源工具usbipd-win,将Windows主机上的物理USB设备“共享”或“附加”到WSL的Linux内核中。对于WSL里的系统来说,这个设备就像直接插在本机一样。
优点:
- 体验最接近原生Linux:在WSL内,设备以
/dev/bus/usb/...的形式存在,ADB会认为这是一个本地USB设备。 - 一次绑定,持久生效:可以配置为自动附加。
缺点:
- 配置相对复杂:需要分别在Windows和WSL安装软件、加载内核模块。
- 对WSL版本有要求:需要WSL 2,且Linux内核版本要支持
usbip。 - 可能存在兼容性问题:并非所有USB设备都能完美映射,尤其是某些需要特定驱动的设备。
2.3 方案三:在Windows安装ADB,在WSL中直接调用(取巧之法)
还有一种非常取巧的思路:既然设备在Windows这边,那我就在Windows上安装好完整的Android SDK Platform-Tools(包含ADB)。然后,在WSL中,我不安装ADB,而是直接通过/mnt/c/...路径去调用位于Windows文件系统里的那个adb.exe。
优点:
- 极简:几乎无需在WSL内进行任何配置,只需要一个可执行文件路径。
- 保证版本统一:电脑上只有一个ADB实例,完全避免版本冲突。
缺点:
- 路径和交互可能别扭:每次命令都要输入长长的Windows路径,或者在WSL里为
.exe设置别名。 - 文件路径转换问题:当ADB命令涉及文件路径参数时(如
adb push、adb install),如果参数是WSL路径(如/home/user/file.apk),传递给adb.exe后,它可能无法正确理解这个Linux路径,需要手动转换为Windows路径(如/mnt/c/Users/...),非常麻烦。 - 环境隔离不彻底:严格来说,这不算“在WSL安装ADB”,更像是“借用”Windows的ADB。
我的选择与建议:对于绝大多数开发者,我强烈推荐方案一(TCP/IP连接)。它平衡了易用性、稳定性和功能性,是社区公认的最佳实践。下文将主要围绕此方案展开,并简要介绍方案二作为备选,方案三仅作了解。
3. 实操详解:搭建TCP/IP调试桥梁
这个方案分为三个明确的阶段:1) 在Windows端准备ADB服务;2) 在WSL端安装ADB客户端;3) 建立两者之间的连接并验证。
3.1 阶段一:Windows主机端的准备工作
首先,我们需要确保Windows这边有一个稳定运行的ADB服务,并开放网络端口。
步骤1:获取Android SDK Platform-Tools如果你已经安装了Android Studio,那么ADB通常已经存在于%LOCALAPPDATA%\Android\Sdk\platform-tools\目录下。如果没有,最简单的方法是直接去 Google开发者官网 下载独立的“Command line tools only”中的Platform-Tools包,解压到一个你喜欢的目录,例如D:\android-sdk\platform-tools\。
步骤2:将ADB添加到Windows系统环境变量PATH这是为了能在任意命令行(包括后续步骤)中方便地调用adb。
- 在Windows搜索栏输入“环境变量”,选择“编辑系统环境变量”。
- 点击“环境变量”按钮。
- 在“系统变量”部分,找到并选中
Path变量,点击“编辑”。 - 点击“新建”,然后将你的
platform-tools文件夹的完整路径(例如D:\android-sdk\platform-tools)添加进去。 - 一路点击“确定”保存。
步骤3:启动ADB服务并设置为TCP/IP模式
- 打开一个Windows命令提示符(CMD)或PowerShell(注意:不是WSL终端)。
- 首先,杀死任何可能已存在的ADB服务:
adb kill-server - 然后,以监听TCP端口的形式启动ADB服务:
adb -a -P 5037 nodaemon server-a: 在所有网络接口上监听。-P 5037: 指定监听端口为5037(ADB默认端口)。nodaemon: 在前台运行,方便观察日志(对于长期使用,你可能想把它配置为后台服务)。
- 此时,命令行会挂起,显示类似
* daemon not running; starting now at tcp:5037的信息,这表明服务已成功启动并在监听。
重要提示:这个PowerShell窗口不能关闭,关闭就意味着服务停止了。对于长期开发,建议将此命令配置为Windows开机启动的任务计划,或者使用
Start-Process等命令在后台运行。一个简单的后台运行方法(在PowerShell中):Start-Process -NoNewWindow adb -ArgumentList "-a -P 5037 nodaemon server"
步骤4:配置Windows防火墙(关键!)这是最容易出错的一步。Windows Defender防火墙可能会阻止来自WSL(被视为网络连接)的入站连接。
- 以管理员身份打开PowerShell。
- 运行以下命令,为ADB服务(
adb.exe)添加入站规则,允许TCP端口5037的通信:New-NetFirewallRule -DisplayName “ADB over TCP (WSL)” -Direction Inbound -Action Allow -Protocol TCP -LocalPort 5037 - 你也可以通过Windows Defender防火墙高级设置图形界面手动创建规则,效果相同。
3.2 阶段二:WSL(Linux)客户端的安装与配置
现在,切换到我们的WSL终端。
步骤1:安装ADB客户端在WSL的Ubuntu(或其他Debian系发行版)中,安装非常简单:
sudo apt update sudo apt install android-tools-adb对于其他发行版,请使用对应的包管理器,如Fedora的dnf install android-tools,Arch的pacman -S android-tools。
步骤2:连接至Windows主机的ADB服务在WSL终端中,我们需要告诉本地的ADB客户端,不要去找本地不存在的USB设备或服务,而是去连接我们Windows主机上运行的服务。
adb connect 172.21.224.1:5037这里的IP地址172.21.224.1需要特别说明。它不是固定的,它是WSL 2为Windows主机分配的虚拟网络接口的IP。你可以通过以下命令在WSL中获取它:
cat /etc/resolv.conf | grep nameserver | awk '{print $2}'通常,这个地址是172.x.x.1的形式。端口5037就是我们之前指定的。
如果连接成功,你将看到类似connected to 172.21.224.1:5037的提示。
步骤3:验证设备列表连接成功后,就可以像在本地一样使用ADB命令了。首先列出设备:
adb devices你应该能看到一个设备条目,地址是172.21.224.1:5037,状态是device。这表示你的WSL ADB客户端已经通过TCP连接,成功地“代理”了Windows主机ADB服务管理的所有设备。
实操心得:你可以将
adb connect命令和获取IP的命令写成一个Shell脚本或别名,放在你的~/.bashrc或~/.zshrc中。例如:alias adb-connect='adb connect $(cat /etc/resolv.conf | grep nameserver | awk '\''{print $2}'\''):5037'这样,每次打开WSL终端,只需要输入
adb-connect即可快速建立连接。
3.3 阶段三:连接物理Android设备并测试
确保你的Android设备已通过USB连接到Windows主机,并在设备上开启了“开发者选项”和“USB调试”。
在Windows的PowerShell(运行着ADB服务的那个)或另一个CMD窗口中,执行:
adb devices你应该能看到你的物理设备,序列号状态为device。这证明Windows端的ADB服务已经正确识别了USB设备。
此时,在WSL终端中再次执行adb devices。你应该会看到两个条目:
172.21.224.1:5037- 这是到Windows ADB服务的连接。- 你的物理设备序列号(如
ABCDEFG) - 这表示通过TCP桥梁,WSL也看到了该设备。
现在,你可以在WSL终端中运行任何ADB命令了,例如安装APK:
adb install /path/to/your/app.apk或者拉取日志:
adb logcat所有命令都会经由TCP连接转发到Windows,再通过USB作用于你的设备,流畅得就像设备直接连在WSL上一样。
4. 备选方案:使用usbipd-win实现USB直通
如果你追求极致的“原生”体验,或者TCP/IP方案在某些复杂场景下遇到问题,可以尝试usbipd-win方案。以下是简要步骤:
在Windows上:
- 从GitHub releases页面安装
usbipd-win。 - 以管理员身份打开PowerShell,运行
usbipd list查看已连接的USB设备,找到你的Android设备(通常由Google或手机制造商标识)。 - 绑定设备:
usbipd bind --busid <设备总线ID>,例如usbipd bind --busid 3-2。
在WSL(Ubuntu)上:
- 确保是WSL 2:
wsl -l -v查看。 - 加载
usbip内核工具:sudo apt install linux-tools-generic hwdata - 更新内核模块索引:
sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/*-generic/usbip 20 - 从Windows附加设备:
sudo usbip attach -r 172.21.224.1 -b <设备总线ID>
成功后,在WSL内执行lsusb应该能看到你的Android设备。然后像在普通Linux上一样使用ADB即可。此方案配置更复杂,且设备重启或重插后可能需要重新绑定和附加。
5. 常见问题与深度排错指南
即使按照步骤操作,你也可能会遇到一些坑。这里记录了几个最常见的问题和解决方法。
5.1 连接被拒绝 (cannot connect to 172.21.224.1:5037: Connection refused)
这是最典型的问题。
- 原因A:Windows端ADB服务未运行。回到Windows PowerShell,检查是否有窗口运行着
adb -a -P 5037 nodaemon server命令,或者该服务是否在后台正常运行。可以用netstat -ano | findstr :5037查看5037端口是否处于LISTENING状态。 - 原因B:防火墙阻止。确认已按照上文步骤添加了防火墙入站规则。可以临时完全关闭防火墙(仅用于测试,不推荐长期使用)来排查。
- 原因C:IP地址错误。确保你
adb connect使用的IP是WSL中通过cat /etc/resolv.conf获取的那个。WSL 2的IP可能会在每次重启后变化。
5.2 WSL中adb devices列表为空,或只有TCP连接没有物理设备
- 原因A:Windows端未识别设备。首先在Windows的CMD/PowerShell里运行
adb devices,确认设备是否已列出且状态为device。如果Windows都看不到,检查USB线、设备开发者选项、USB调试授权弹窗等。 - 原因B:WSL到Windows的TCP连接不稳定。尝试在WSL中先
adb disconnect 172.21.224.1:5037,再重新adb connect。 - 原因C:ADB版本不匹配(极罕见)。理论上TCP连接对版本要求不严,但如果差异巨大,可能有问题。确保Windows和WSL两边的ADB版本不要太古老。用
adb version查看。
5.3 文件操作命令(push/pull)路径问题
在TCP/IP方案下,当你使用adb push从WSL推送文件到设备时,源路径是WSL内的Linux路径(如/home/user/test.txt),这没有问题。但是,如果你在Windows端直接操作ADB,或者思考文件存在哪里,需要理解:文件数据流经了网络,但文件的“源”被ADB客户端(WSL端)正确读取了。唯一需要注意的是:如果你尝试推送一个位于Windows盘符(如/mnt/c/Users/...)下的文件,在WSL的ADB中也是完全可以的,因为WSL能访问这些路径。
5.4 性能与稳定性考量
TCP/IP连接非常稳定,对于绝大多数调试、安装、日志操作,感知不到延迟。但在进行超大文件(如数GB的系统镜像)传输时,网络开销可能会比原生USB稍慢一点点,但在千兆内网环境下差异微乎其微。稳定性方面,只要Windows端的服务不中断,连接就会一直保持。如果Windows进入睡眠或休眠,网络连接可能会中断,需要重新adb connect。
5.5 多设备管理
当Windows主机连接了多台Android设备时,WSL中的adb devices也会列出所有设备。你可以使用-s <序列号>参数来指定对哪台设备进行操作,序列号就是adb devices列表中显示的那一串。这对于同时测试多台手机的场景非常方便。
6. 进阶技巧与自动化脚本
为了让这个工作流更加丝滑,这里分享几个我日常使用的技巧。
技巧1:一键连接脚本在WSL的~/.bashrc或~/.zshrc末尾添加以下函数:
function wsl-adb() { local host_ip=$(grep nameserver /etc/resolv.conf | awk '{print $2}') adb connect ${host_ip}:5037 > /dev/null 2>&1 if [ $? -eq 0 ]; then echo “✅ ADB connected to Windows host at ${host_ip}:5037” adb devices else echo “❌ Failed to connect to ADB server. Is it running on Windows?” fi }这样,打开终端输入wsl-adb,就能自动获取IP并连接,同时显示设备列表。
技巧2:在WSL中直接启动Windows端的ADB服务(需要Windows配置)这需要一些额外的配置,使得WSL能通过网络远程启动Windows上的一个进程。一个相对安全的方法是使用Windows的schtasks创建一个计划任务来启动ADB服务,然后WSL通过net rpc或SSH到Windows来触发该任务。但这涉及更多权限和配置,对于普通用户,更推荐将Windows端的ADB服务配置为开机自启的后台服务(使用NSSM或WinSW等工具),一劳永逸。
技巧3:结合VS Code Remote - WSL进行开发如果你使用VS Code进行Android开发,并安装了“Remote - WSL”扩展,那么你可以在WSL中完美运行整个开发环境。ADB在WSL中配置好后,VS Code里的Android插件(例如,用于Flutter或React Native)就能直接调用WSL终端中的ADB命令,实现编码、调试、设备管理的全流程在Linux环境下完成,体验非常统一。
折腾WSL下的ADB,看似是个小问题,实则串联起了Windows与Linux子系统之间的网络、服务、硬件访问等多个知识点。经过这样一番配置,你获得的不仅仅是一个能用的ADB命令,更是一套理解WSL与主机如何协同工作的思维模型。这套TCP/IP桥接的方案,其思想同样可以借鉴到其他需要在WSL中访问Windows主机服务的情景中。