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

Android emulator命令行无法终止,Mac Shell脚本执行受阻求助

解决Android模拟器启动阻塞Shell脚本的多设备截图自动化方案

嘿,我完全懂你碰到的这个麻烦——启动模拟器的命令卡着不动,脚本没法往下跑后续的截图逻辑,强制终止还没用,只有等模拟器已经在运行时脚本才能正常执行对吧?我之前做多设备自动化测试时也踩过这个坑,给你几个实用的解决思路和完整脚本示例,帮你搞定多设备截图自动化:


核心问题分析

启动Android模拟器的emulator命令默认会占据当前终端的前台进程,并且持续输出日志,导致脚本被阻塞,后续代码根本没机会执行。就算你用Ctrl+C强制终止,有时候模拟器进程还会残留,反而更麻烦。所以我们需要两个关键操作:

  1. 把模拟器启动命令放到后台运行,并屏蔽不必要的输出
  2. 等待模拟器完全启动就绪后再执行截图操作(不然截图会失败)

具体解决方案

1. 后台启动模拟器并屏蔽输出

把原来的启动命令改成这样,让它在后台默默运行,不会阻塞脚本:

# 替换成你的AVD名称
emulator -avd YourAVDName > /dev/null 2>&1 &
  • > /dev/null:把标准输出(模拟器的日志)扔到“黑洞”,不显示在终端
  • 2>&1:把错误输出也重定向到和标准输出一样的地方,避免报错信息干扰
  • &:让命令在后台进程中运行,脚本可以继续执行后续代码

2. 等待模拟器完全就绪

光启动模拟器还不够,得等系统完全启动完成(比如桌面加载好)才能截图。可以通过检查Android系统的sys.boot_completed属性来判断,写一个复用的等待函数:

wait_for_emulator() {
  local emulator_id=$1
  echo "等待模拟器 $emulator_id 启动完成..."
  while true; do
    # 获取系统启动状态,忽略可能的adb连接错误
    boot_status=$(adb -s $emulator_id shell getprop sys.boot_completed 2>/dev/null)
    # 当返回值为1时,表示系统启动完成
    if [[ "$boot_status" == "1" ]]; then
      sleep 2  # 额外等2秒确保系统稳定
      echo "模拟器 $emulator_id 已就绪!"
      break
    fi
    sleep 3  # 每3秒检查一次
  done
}

3. 多设备自动化完整脚本

下面是一个可以直接复用的多设备截图脚本,它会自动检查AVD是否已经运行,启动未运行的模拟器,等待就绪后执行截图并保存到本地:

#!/bin/bash

# 配置:定义要截图的AVD列表
AVDS=("Pixel_5_API_30" "Pixel_7_API_33" "Nexus_6_API_28")
# 截图保存目录
SCREENSHOT_DIR="./emulator_screenshots"

# 创建保存目录(如果不存在)
mkdir -p $SCREENSHOT_DIR

# 等待模拟器就绪的函数
wait_for_emulator() {
  local emulator_id=$1
  echo "等待模拟器 $emulator_id 启动完成..."
  while true; do
    boot_status=$(adb -s $emulator_id shell getprop sys.boot_completed 2>/dev/null)
    if [[ "$boot_status" == "1" ]]; then
      sleep 2
      echo "模拟器 $emulator_id 已就绪!"
      break
    fi
    sleep 3
  done
}

# 遍历所有AVD,执行截图流程
for avd in "${AVDS[@]}"; do
  # 检查当前AVD是否已经在运行
  running_emulator_id=""
  # 遍历所有已连接的模拟器设备,匹配AVD名称
  while read emulator_id _; do
    if [[ "$emulator_id" == emulator* ]]; then
      avd_name=$(adb -s $emulator_id emu avd name 2>/dev/null)
      if [[ "$avd_name" == "$avd" ]]; then
        running_emulator_id=$emulator_id
        break
      fi
    fi
  done < <(adb devices)

  if [[ -n "$running_emulator_id" ]]; then
    echo "AVD $avd 已在运行,跳过启动步骤..."
    emulator_id=$running_emulator_id
  else
    echo "启动AVD $avd..."
    # 后台启动模拟器,屏蔽所有输出
    emulator -avd "$avd" > /dev/null 2>&1 &
    # 等待设备被adb识别(给模拟器一点启动时间)
    sleep 10
    # 获取刚启动的模拟器ID
    emulator_id=$(adb devices | grep emulator | head -n1 | awk '{print $1}')
  fi

  # 等待模拟器完全就绪
  wait_for_emulator "$emulator_id"

  # 执行截图操作
  timestamp=$(date +%Y%m%d_%H%M%S)
  screenshot_name="screenshot_${avd}_${timestamp}.png"
  echo "为 $avd 执行截图..."
  adb -s "$emulator_id" screencap -p /sdcard/$screenshot_name
  adb -s "$emulator_id" pull /sdcard/$screenshot_name "$SCREENSHOT_DIR/$screenshot_name"
  # 清理模拟器上的临时截图文件
  adb -s "$emulator_id" shell rm /sdcard/$screenshot_name

  echo "$avd 的截图已保存到:$SCREENSHOT_DIR/$screenshot_name"
done

echo "所有多设备截图任务已完成!"

注意事项

  • 确保adb和emulator命令在你的系统PATH中,如果找不到,可以用完整路径(比如~/Library/Android/sdk/emulator/emulator和~/Library/Android/sdk/platform-tools/adb)
  • 第一次启动模拟器可能需要更长时间,你可以根据实际情况调整sleep的时长
  • 如果遇到adb连接问题,可以先执行adb kill-server再重新启动adb服务

内容的提问来源于stack exchange,提问作者Son Nguyen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:42:48