如何通过Python脚本向adb shell执行的进程传入输入内容?
问题根因
- 初始化
subprocess.Popen时未配置stdin=subprocess.PIPE,没有建立向子进程写入数据的通道,根本无法传入输入内容。 - 默认执行
adb shell时会为Android侧进程分配伪终端,加上默认的块缓冲机制,写入的输入如果不做特殊处理不会被即时推送到目标进程,表现为进程卡住无响应。 - 传入字符串命令+
shell=True的写法会额外嵌套一层本地shell进程,输入输出链路多一层转发,很容易出现阻塞、缓冲不刷新的问题。
可直接运行的修复代码
import subprocess # 命令用列表形式传递,禁用shell=True减少中间转发层,-T参数关闭adb的tty分配,解决缓冲卡住问题 cmd = ["adb", "shell", "-T", "libtest_ip"] p = subprocess.Popen( cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True # Python3.7+支持,自动处理编解码,无需手动转bytes ) # 传入输入,每个输入项末尾必须加\n,模拟终端回车提交操作 input_data = "1\nen_us\n" # communicate会一次性把输入写入进程,等待进程执行完成后返回所有输出 stdout, stderr = p.communicate(input=input_data, timeout=15) print("程序标准输出:\n", stdout) print("程序错误输出:\n", stderr)
交互式场景适配
如果libtest_ip是动态交互逻辑,需要根据上一步输出决定下一次输入,不要用communicate()(该方法会等待进程结束才返回),直接操作stdin管道即可,注意写完必须强制刷新缓冲:
import time # 写入第一个输入 p.stdin.write("1\n") p.stdin.flush() # 按需等待程序处理,也可以读p.stdout的内容判断处理进度 time.sleep(0.3) # 写入第二个输入 p.stdin.write("en_us\n") p.stdin.flush() # 执行完成后回收资源 p.stdin.close() return_code = p.wait()
额外注意事项
- 如果加了
-T参数还是存在缓冲卡住的问题,可以把命令换成["adb", "exec-out", "libtest_ip"],exec-out不会经过Android侧的shell中转,直接执行二进制文件,输入输出链路更短,缓冲问题更少。 - 开启stdout/stderr管道后,不要持续写入stdin却不读取输出,管道缓冲区占满后会触发死锁。如果不需要捕获输出,可以把stdout/stderr参数设为
subprocess.DEVNULL。 - 所有传给进程的输入内容末尾必须加换行符,否则程序会认为输入还没提交,一直等待回车。
内容的提问来源于stack exchange,提问作者user1658384
相关产品推荐
相关产品推荐

