如果你用过安卓调试,多半遇到过这样的瞬间:手机连上电脑,敲了一行adb devices却提示unauthorized;或者想把电脑上的文件推给手机,结果push和pull的方向反了,直接把手机文件覆盖掉了。这时候最靠谱的求助对象,其实是终端里那一屏密密麻麻的英文帮助文本——也就是adb help。
但问题也很现实:满屏英文术语,每个单词都认识,连起来却不知道在说什么。很多朋友在 QQ 群、论坛里问"adb 帮助文档有没有中文版?"、"这些命令到底怎么用?",其实adb help本身就把所有命令都写在里面了,只是缺一份"人话翻译 + 场景化的用法注解"。所以这篇文章不打算给你罗列几十条命令的流水账,而是把adb help里的关键段落逐条拆开,用中文说清楚每个参数、每条命令背后的逻辑,顺便补上我在日常开发、救砖、刷机、抓 log 过程中踩过的坑。
这篇文章适合谁看?刚开始接触 ADB 的安卓爱好者、经常和真机测试打交道的客户端开发、以及需要远程协助父母清理手机问题但不想装全家桶工具的普通用户。看完之后,你再遇到adb devices识别不到设备、adb install失败、adb reverse和adb forward分不清这类问题,基本都能靠自己用 help 文档定位。
1. 为什么说看懂 adb help 比背命令更重要
1.1 帮助文档是命令的"官方白皮书"
先摆一个反直觉的观点:我从来不建议去背adb命令清单,而是建议把adb help当成第一份参考资料。原因很简单,命令行工具的帮助文档是开发者在发布工具时同步维护的"官方白皮书",它包含了当前版本所有支持的命令、参数、默认值,以及一些你用搜索引擎搜半天都搜不到的旧版本遗留行为。
比如你搜"adb 如何无线连接手机",网上很多教程会给你写adb connect 192.168.x.x:5555,但没人告诉你5555是默认端口,在 help 文档里其实用一行[default port 5555]就写清楚了。再比如adb install后面那一串[-lrtsdg],很多人都只知道-r是覆盖安装,但-d允许降级安装、-g授予所有运行时权限,这几个参数在帮助文档里都有,只是你平时没留意。
所以,看懂adb help不是让你把英文翻译成中文背下来,而是让你在看懂之后,建立起"哦,原来这个命令支持这么多选项"的意识。以后遇到问题,你能第一时间想到"help 里是不是有相关参数",而不是到处找杂七杂八的博客。
1.2 常见误区:翻译文档不等于会用命令
还有一种心态也常见:觉得只要把帮助文档翻译成中文,命令就会用了。这其实是个大坑。翻译只是第一步,比翻译更重要的是理解命令背后的执行模型。
拿adb forward和adb reverse来说,文档原文只是给了语法:
forward [--no-rebind] LOCAL REMOTE reverse [--no-rebind] REMOTE LOCAL翻译成中文很简单:"本地端口转发到设备端口"、"设备端口转发回本地端口"。但如果你不理解什么是"端口转发",什么是"TCP 连接的方向",依然不知道怎么用。
再比如adb shell在 help 文档里就一行:
shell [-e ESCAPE] [-n] [-Tt] [-x] COMMAND...但实际使用中,adb shell后面直接跟命令和不跟命令进入交互式 shell,行为差异很大;-t参数在部分设备上还会影响PTY的分配,进而导致某些命令(比如top)输出格式不同。这些细节文档里不会展开解释,需要结合实战去理解。
所以这篇文章既是一份"中文翻译稿",也是一份"场景化注解"——我会把帮助文档里每一段命令放到真实使用场景里讲,告诉你这条命令通常在什么情况下出现,参数怎么选,选错了会有什么后果。
2. 全局选项部分逐条翻译:那些不起眼的 -a -d -e -s 到底在说什么
adb help的第一大部分是global options,也就是全局选项。这些选项放在adb和具体子命令之间,控制的是整个 adb 命令的运行方式,而不是某个子命令的行为。常见的输出是:
-a listen on all network interfaces, not just localhost -d use USB device (error if multiple devices connected) -e use TCP/IP device (error if multiple TCP/IP devices available) -s SERIAL use device with given serial (overrides $ANDROID_SERIAL) -t ID use device with given transport id -H name of adb server host (default: localhost) -P port of adb server (default: 5037) -L SOCKET listen on given socket for adb server (default: tcp:5037)2.1 设备选择三兄弟:-d、-e、-s
如果你只有一台手机连电脑,这些选项基本用不上。但只要你的电脑上插了两台手机、又跑着一个模拟器,adb devices会给你列出一长串,这时候你就得靠-s来指定设备。
-d表示选择当前通过 USB 连接的设备(如果检测到多个 USB 设备,报错)。-e表示选择当前通过 TCP/IP 连接的设备(也就是无线调试的模拟器或手机)。-s SERIAL则是直接指定设备的序列号,比如adb -s emulator-5554 shell就是操作这台模拟器。
实战里最常用的其实是-s。因为我经常一台电脑连着两个设备:一台小米手机做性能测试,一台 Pixel 做系统兼容性测试。如果不用-s直接adb install,adb 会报错:
adb: more than one device/emulator这个more than one device/emulator的报错,翻译过来就是"你让我操作谁?"——help 文档里早早写明白了-s SERIAL的用途,很多朋友却要等到报错才回来查。
-s后面跟的SERIAL可以用adb devices -l查看,例如adb -s 192.168.1.5:5555 shell也可以直接写远程设备的 IP 和端口,方便在无线调试时切换设备。
2.2 传输与监听参数:-H、-P、-L 的适用场景
-H、-P、-L这三个选项平时很少用,但在某些特殊环境里能救命。它们的含义分别是:
-H:指定 adb server 的主机名,默认是localhost。如果你把 adb server 跑在局域网里的另一台电脑上,用这台电脑的 adb 客户端去操作设备,就需要指定-H 192.168.1.10。-P:指定 adb server 的端口,默认是5037。如果你的 5037 端口被其他程序占用了(比如老版本的模拟器、某些安卓工具箱),adbd 会起不来,此时可以用-P 5039换一个端口。-L SOCKET:直接指定 adb server 监听的 socket 地址,格式是tcp:端口。这个属于更底层的高级用法,一般不需要碰。
看到这里你可能会问:adb不是一条命令直接连手机吗,怎么还有 server?是的,这就是 ADB 的工作模型:adb 客户端(你敲的命令)不会直接和手机通信,而是先和本机后台的 adb server 通信,再由 server 统一管理设备列表和连接。所以adb start-server/adb kill-server本质上是在管理这个本地服务进程。
2.3 多设备场景下如何用 -t 和 serial 精准定位
-t ID用 transport id 来指定设备,这里的数据来自adb devices -l输出里的transport_id。平时我们更习惯用-s指定 serial,示例:
adb devices -l # 输出示例: # emulator-5554 device product:sdk_gphone model:sdk_gphone device:generic_x86 transport_id:1 # 192.168.1.3:5555 device product:raven model:Pixel_6 device:raven transport_id:2如果要操作 transport_id 为 2 的那台设备,可以写adb -t 2 shell。这在写自动化脚本时很有用,因为你可以在脚本里解析adb devices -l的输出来动态获取 transport_id,而不用硬编码 serial。
还有一个小经验:-s支持补全匹配规则?不支持。-s必须匹配完整 serial 或者模糊匹配的前缀,但建议写全,避免误操作。.env文件、CI 环境变量里设了ANDROID_SERIAL的话,-s会覆盖这个环境变量,这一点 help 文档里明确写了overrides $ANDROID_SERIAL。
3. general commands 与 networking 段解读:连接设备的第一步
global options往下,就是general commands和networking两块。它们看起来很简单,但很多人在这里就容易卡住。
3.1 devices、help、version 背后的信息量
devices [-l] list connected devices (-l for long output) help show this help message version show version num这三条命令里,devices的使用频率最高,而且-l这个参数被大多数人忽略。adb devices只显示三列:序列号、状态、类型描述。adb devices -l会额外显示model、product、device、transport_id等字段。当你有多台同型号手机连电脑时,用-l才能区分哪台是哪个。
顺便说一句,adb devices输出中的设备状态一共就几种:
device:正常,已连接并授权。unauthorized:设备已连接,但还没在手机上点击"允许 USB 调试"弹窗。offline:设备连接了但通信有问题,可能是 adb server 版本不匹配、USB 线松了、或者是设备休眠。no permissions:Linux/Mac 上常见,一般是 USB 权限问题。
version命令打印的是 adb 二进制版本和 server 版本。如果你发现adb devices显示设备状态是offline,可以对比一下adb version的输出和手机端/模拟器端的 adb 版本,版本差距太大时会导致协议兼容问题,解决办法通常是换同一个版本的 adb 工具包。
3.2 connect/disconnect:无线调试的入口
connect HOST[:PORT] connect to a device via TCP/IP [default port 5555] disconnect [HOST[:PORT]]adb connect是用来做无线调试的。使用前提是手机和电脑在同一局域网下,而且手机端需要先开启"无线调试"或通过 USB 连接后执行adb tcpip 5555打开 adb 对 TCP/IP 端口的监听。
很多教程让你直接adb connect 192.168.1.7:5555,但如果你忘了端口号,help 文档已经用[default port 5555]告诉你了。实际上,部分手机(比如 MIUI 的"无线调试")使用的端口是随机的,需要在手机的开发者选项里查看 IP 和端口,这时候connect的PORT必须显式写,不能省。
disconnect如果不带参数,会断开所有 TCP/IP 连接;带参数的话只断开指定设备。这个命令我经常用于清理"已经掉线但还占着列表"的无线设备。
3.3 forward/reverse:端口转发的方向不要搞反
networking段落里最容易让人懵的就是forward和reverse:
forward --list list all forward socket connections forward [--no-rebind] LOCAL REMOTE forward --remove LOCAL reverse --list list all reverse socket connections reverse [--no-rebind] REMOTE LOCAL reverse --remove REMOTE简单记忆方式:
forward是 "电脑上的端口" 转发到 "手机上的端口"。例如adb forward tcp:8080 tcp:8080,之后你访问电脑的http://localhost:8080,实际上会打到手机里的localhost:8080。reverse是反过来的:让手机上的端口转发到电脑上的端口。例如adb reverse tcp:8081 tcp:8080,之后手机访问http://localhost:8081,会转发到电脑的8080端口。
这两个命令最典型的场景是开发和调试 Web 页面。比如你在电脑上跑了一个Vite开发服务器,端口是 5173,手机访问电脑 IP 不太方便(可能不在同一网段),这时候adb reverse tcp:5173 tcp:5173,手机直接访问http://localhost:5173就能打开电脑上的开发页面,非常实用。
--no-rebind参数的意思是:如果这个端口已经被 forward/reverse 占用了,不要重新绑定,直接报错。默认情况下,如果不加--no-rebind,重复设置同一个端口会覆盖之前的设置;加上之后则会更安全,防止你误覆盖了其他服务。我在写自动化测试脚本时,会在脚本开头先forward --remove再重新绑定,确保环境干净。
4. 文件传输与 shell 命令的文档翻译与细节补全
4.1 push/pull:传文件别忽略权限和目录
push LOCAL... REMOTE copy local files/directories to device pull REMOTE... LOCAL copy files/directories from devicepush是从电脑往设备上传文件,pull是从设备往电脑下载文件。翻译没问题,但有几个细节值得展开。
第一,push和pull都支持目录操作。push本地目录时,如果设备端目录不存在,adb 通常会帮你创建;但如果父目录没有写权限,会报Permission denied。比如你想把文件推到/system/目录,普通adb push肯定失败,因为/system分区是只读的,需要先adb root+adb remount或者用adb disable-verity之类的操作(后面会讲)。
第二,pull设备端文件时,如果文件名包含特殊字符(空格、中文),建议用引号包起来,否则 adb 可能会解析错误。
第三,push支持一次推多个文件:
adb push a.txt b.txt /sdcard/Download/help 文档里写的LOCAL...就表示可以多个源文件。
有一点要提醒:adb pull在拉取目录时,默认不会保留设备端文件的权限和所有者信息,只会处理内容。如果拉取的是 app 私有目录(比如/data/data/包名/),通常会因为权限问题失败,这时候需要设备已经 root,或者用run-as配合exec-out来拉取,后面会讲。
4.2 shell 与 exec-out:区别和取舍
shell [-e ESCAPE] [-n] [-Tt] [-x] COMMAND... exec-out COMMAND... copy the raw output of a command directly to the local shelladb shell是使用频率最高、也最容易被误用的一条命令。它有两种用法:
adb shell不带参数:进入设备上的交互式 shell,你会看到一个/ $或/ #提示符。adb shell 具体命令:直接在电脑端执行命令并返回结果。
很多人在命令行里写adb shell "cd /sdcard && ls",这样是可以的。但要注意双引号里的&&是给设备 shell 解析的,不是给电脑解析的。如果你不加引号,写成adb shell cd /sdcard && ls,电脑会先执行cd /sdcard(在电脑里,通常会失败),然后才在设备里执行ls,这就完全错了。
exec-out的用途比较特殊:它把设备端命令的原始输出直接传给当前终端,不做额外的换行、转义处理。比如你想把设备上的图片拉出来显示,或者把dumpsys的输出导入本地文件,用exec-out更合适:
adb exec-out screencap -p > screenshot.png如果用adb shell screencap -p > screenshot.png,可能会因为 CRLF 换行符导致图片打不开(Windows 下尤其明显),而exec-out能避免这个问题。
shell还有一个常见参数-t,它为要执行的命令分配一个PTY(伪终端)。某些命令在非 PTY 模式下输出结果格式不同,比如adb shell top如果不用-t,输出会被强制转成单列模式(可能是因为检测到非交互终端后自动切换了某种兼容模式);加上-t后,输出就是完整的动态表格。如果你观察过adb shell -t top和adb shell top的差别,就会明白为什么 help 文档里会有这个参数。
4.3 pm/am 不是命令,而是一整个子命令家族
shell命令段落后面紧跟两个被隐藏了大半内容的条目:
pm perform package manager (package manager commands) am start activities and get information on activitieshelp 文档里没有把pm和am的子命令全部列出来,因为它们各自还有自己的帮助文档。你需要执行adb shell pm help或adb shell am help才能看到完整子命令。
这也是一个很重要的思路:当一条帮助文档里的命令本身是一个"子命令族"时,不要指望adb help告诉你一切,得继续用adb shell 子命令 help去深入。
pm常见用法举例:
adb shell pm list packages # 列出所有包名 adb shell pm list packages -3 # 只列出第三方应用 adb shell pm clear 包名 # 清空应用数据 adb shell pm install-existing 包名 # 恢复被卸载的系统应用 adb shell pm uninstall --user 0 包名 # 为当前用户卸载应用(不需要 root,很多系统应用可以用这个命令禁用)am常见用法:
adb shell am start -n 包名/Activity名 # 启动指定 Activity adb shell am force-stop 包名 # 强停应用 adb shell am broadcast -a 广播Action # 发送广播在adb help里,pm和am只是两个占位符,真正要查子命令得用各自的帮助。翻译这类命令时,需要把"pm 是 Package Manager,am 是 Activity Manager"这个底层含义也带进来,才能知道它们能干什么。
5. 安装、调试与安全命令的文档翻译与实战坑点
5.1 install 和 uninstall 的参数拆解
install [-lrtsdg] [--instant] PACKAGE install-multiple [-lrtsdgp] PACKAGE... uninstall [-k] PACKAGEinstall的参数在帮助文档里很简洁,但每个字母都对应一种场景:
-l:锁定应用(将设备应用锁定到前台?其实是 "install with forward-lock" 的意思,这个参数已经很少用)。-r:重新安装,保留数据。这是覆盖安装最常用的参数。-t:允许安装测试包(AndroidManifest 里android:testOnly="true"的 APK 必须加-t才能安装)。-s:安装到 SD 卡(很多设备已经不支持了,报错忽略)。-d:允许降级安装,也就是手机上的版本号比 APK 里的版本号高时,加上-d可以强制覆盖。-g:安装完成后自动授予所有运行时权限。这对测试很有用,省得每次装完应用还要手动点一堆权限弹窗。
install-multiple后面这些参数加了-p,意思是部分安装?实际上是用于同时安装多个 APK 的,适合 split APK(例如 Android App Bundle 生成的.apk拆分包)。用法示例:
adb install-multiple base.apk split_config.xhdpi.apk split_config.en.apk从 Android 11 开始,adb install也支持 split APK 了,用--install-multiple语法可能更明确。不过平时使用中,我建议直接adb install-multiple,兼容性更好。
uninstall [-k]的-k参数表示卸载应用但保留/data/app下的数据。不过 Android 版本越高,-k的限制越多;在 Android 10 及以上,非系统应用可能直接忽略-k。不要指望-k能像旧版本那样完整保留私有数据。
5.2 logcat 的常用过滤组合
debugging段里最常用的无疑是logcat,帮助文档只有一句:
logcat show device log (logcat --help for more)实际上logcat自己的帮助文档信息量巨大。日常调试我常用的组合有:
adb logcat -c # 清空日志 adb logcat -v time # 输出带时间戳,可读性好 adb logcat -s TAG # 按 Tag 过滤(silent 对其他标签) adb logcat *:W # 只输出 warning 及以上级别 adb logcat | grep -E "关键字" # 在本地过滤还有个冷门的-b参数,可以指定查看main(主日志)、system(系统日志)、events(事件日志)、crash(崩溃日志)等 buffer。比如:
adb logcat -b crash这条命令只显示崩溃日志,比在满屏日志里人工找FATAL EXCEPTION高效得多。
logcat在 Windows 下用findstr过滤和在 Mac/Linux 下用grep过滤效果不同,实践中注意一下终端编码,避免中文乱码。
5.3 disable-verity 和 keygen 是什么情况下才需要碰
disable-verity disable dm-verity checking on userdebug builds enable-verity re-enable dm-verity checking on userdebug builds keygen FILE generate a new RSA key pair for ADB authenticationdisable-verity和enable-verity不是给普通用户用的。dm-verity 是安卓系统的启动时完整性校验机制,主要用于防止分区被篡改。只有userdebug或eng版本的系统才允许关闭校验;如果你用官方稳定版系统去执行adb disable-verity,大概率会提示无法操作。
那什么时候需要 disable-verity?当你需要修改/system分区并保持修改持久生效时,比如精简系统应用、替换系统字体、反编译后重新打包系统应用,就要先adb root,再adb disable-verity,然后重启设备,最后adb remount。这个流程里任何一步出错都可能导致无法开机,所以非必要别碰。
keygen FILE的作用是生成一对新的 RSA 密钥,用来做 ADB 身份验证。电脑第一次连接手机时,会生成一对密钥,公钥被推送到手机;之后每次连接都用这个密钥做签名验证。如果某一天你换电脑了,或者手机里的授权列表被清空,就会遇到unauthorized。这时可以执行adb keygen $HOME/.android/adbkey重新生成密钥对,但需要重新在手机上点授权。
需要提醒的是:不要随便删掉~/.android/adbkey文件。删掉后所有设备的授权都要重新确认,如果设备已经无法触屏,这个问题会变得很棘手。更稳妥的做法是备份这一对文件(adbkey和adbkey.pub)。
6. 把翻译变成自己的排查手册:三套速查思路
6.1 按场景聚合命令,而不是按字母表
adb help里的命令排布是按功能分组的:global options、networking、file transfer、shell、app installation等。但我们在日常使用时,脑中的组织方式应该是"场景",而不是"帮助文档的目录"。
我自己的速查手册分四类:
- 设备连接类:
devices -l、connect、disconnect、-s指定设备。 - 文件与数据类:
push、pull、exec-out、shell。 - 应用操作类:
install、uninstall、pm list packages、am force-stop。 - 调试分析类:
logcat、dumpsys、screencap、keygen。
当你碰到问题时,先判断属于哪一类,然后从这一类里找对应命令。比如"手机连不上电脑",先看设备连接类,查adb devices的状态;如果是unauthorized,去检查手机上的授权弹窗,不要瞎翻 help。
6.2 用 adb help 定位"命令不存在"问题的经验
很多人遇到过这种情况:照着网上的教程输入adb xxx,提示unknown command xxx。这时候不要怀疑是 ADB 装错了,先执行adb help看看当前版本是否包含这个命令。
比如早期版本没有adb exec-out,如果你用的老版本 adb 输入adb exec-out就会报错。这时候要么升级 adb 版本,要么改用等价命令。再比如adb shell settings这个命令其实不是 adb 层级的,而是 shell 层级的,很多人误写成adb settings,自然报错。
所以正确姿势是:命令报错时,先判断这个命令是属于 adb 客户端(adb xxx)还是属于设备端的 shell(adb shell xxx)。adb help里列出的都是客户端命令;而pm、am、settings、dumpsys、screencap这些都需要在adb shell后面执行,或者在进入 shell 后执行。
这类错误我见过太多了:把adb shell pm list packages写成adb pm list packages,然后来问我为什么命令找不到。其实只要看一眼帮助文档的shell段落,就能理解pm只是传给 shell 的一个参数。
6.3 我的个人翻译习惯和推荐做法
最后聊聊我对"ADB 命令帮助文档中文翻译"这个事情的实操建议。
我给自己的要求是:不逐字翻译,而是翻译"用途 + 参数场景"。比如adb shell input text这个命令,帮助文档里可能只有一行input text <text>,翻译成中文时我会写:
模拟输入文本,
text中的空格要用%s代替,特殊字符需要转义。比如adb shell input text "hello%sworld"会输入 "hello world"。
这种"翻译"比单纯的英文转中文更有价值。
另外一点:用熟了 help 之后,也要知道有些命令的细节在 help 之外。比如adb bugreport会收集大量系统信息,adb backups在 Android 12 之后已经废了大半,这些信息在adb help里要么没有,要么非常简略。所以我通常会把官方文档(https://developer.android.com/tools/adb)里更新、更详细的表格和 help 文档对照着看。中英文对照的记笔记方式我推荐用表格:命令、英文原文、参数、中文用途、坑点,这样一列下来,基本就是一份属于你自己的中文帮助手册。
这里分享一个小技巧:把你自己整理的速查表放在~/.adb_cheatsheet.md或者公司内部的知识库里,遇到问题先查自己的表,比打开浏览器搜"adb xxx 用法"快得多,而且不会被过时博客带偏。