14、Fastboot脚本化:编写批处理脚本自动化刷机、使用Python调用Fastboot命令

刷机这事儿,一次两次还行,次数多了真能让人崩溃。我记得刚入行那会儿,给测试组刷几十台设备,每台都得手动敲命令、等进度、再敲下一条。一天下来,手指头都快抽筋了。后来我琢磨着,这活儿能不能让机器自己干?于是就有了今天要聊的——Fastboot脚本化。

说白了,就是把那些重复的刷机命令,写进一个脚本文件里。双击一下,喝杯咖啡,回来机器就刷好了。嗯,这才是工程师该有的样子。

为什么需要脚本化?

你想想看,一个完整的刷机流程通常包括:

  • 解锁bootloader(如果没解过)
  • 刷入boot分区
  • 刷入system分区
  • 刷入vendor分区
  • 擦除userdata
  • 重启设备

这些命令加起来少说五六条,多则十几条。每次手动输入,不仅慢,还容易出错。我在项目中遇到过,有同事漏刷了vendor分区,结果设备开机后WiFi打不开,排查了半天才发现问题。

脚本化之后,这些风险就大大降低了。而且,脚本可以复用、可以分享、可以版本控制。这才是专业团队该有的工作方式。

批处理脚本(Windows平台)

Windows下最直接的方式就是写一个.bat文件。别觉得批处理很low,它其实非常实用。

来看一个我常用的刷机脚本模板:

@echo off
echo ========================================
echo   Fastboot 自动刷机脚本 v1.0
echo   作者:蓝海资料掘金营
echo ========================================

:: 检查设备是否连接
fastboot devices
if %errorlevel% neq 0 (
    echo [错误] 未检测到Fastboot设备,请检查连接
    pause
    exit /b 1
)

:: 解锁bootloader(如果需要)
echo [步骤1] 解锁bootloader...
fastboot flashing unlock
echo 请在设备上确认解锁操作
pause

:: 刷入各分区
echo [步骤2] 刷入boot分区...
fastboot flash boot boot.img
if %errorlevel% neq 0 (
    echo [警告] boot分区刷入失败,继续执行...
)

echo [步骤3] 刷入system分区...
fastboot flash system system.img

echo [步骤4] 刷入vendor分区...
fastboot flash vendor vendor.img

:: 擦除数据
echo [步骤5] 擦除userdata...
fastboot erase userdata
fastboot erase cache

:: 重启
echo [步骤6] 刷机完成,重启设备...
fastboot reboot

echo ========================================
echo   刷机流程全部完成!
echo ========================================
pause

这里有几个要点:

  • @echo off 可以隐藏命令本身,只显示输出,界面更清爽
  • %errorlevel% 是Windows批处理中获取上一条命令返回码的方式
  • pause 在关键步骤暂停,给操作者确认的时间
注意:批处理脚本中的路径建议使用绝对路径,或者把脚本和镜像文件放在同一个目录下。我曾经因为路径写错,刷了个不存在的镜像进去,结果设备变砖了。嗯,那次折腾了一下午才救回来。

Python调用Fastboot命令

批处理虽然简单,但功能有限。如果你需要更复杂的逻辑——比如根据设备型号选择不同的镜像、记录刷机日志、并行刷多台设备——那就得上Python了。

Python调用外部命令,最常用的就是subprocess模块。我个人习惯用subprocess.run(),它简单直接,适合大多数场景。

来看一个Python刷机脚本的示例:

import subprocess
import sys
import time
import os

def run_fastboot_command(cmd, description=""):
    """执行Fastboot命令并返回结果"""
    if description:
        print(f"[{time.strftime('%H:%M:%S')}] {description}...")
    
    try:
        result = subprocess.run(
            cmd,
            shell=True,
            capture_output=True,
            text=True,
            timeout=120  # 超时时间120秒
        )
        
        if result.returncode == 0:
            print(f"  ✓ 成功: {result.stdout.strip()}")
            return True
        else:
            print(f"  ✗ 失败: {result.stderr.strip()}")
            return False
            
    except subprocess.TimeoutExpired:
        print(f"  ✗ 超时: 命令执行超过120秒")
        return False
    except Exception as e:
        print(f"  ✗ 异常: {str(e)}")
        return False

def flash_device(images_dir):
    """刷机主流程"""
    print("=" * 50)
    print("  Fastboot 自动刷机工具")
    print("=" * 50)
    
    # 1. 检查设备
    if not run_fastboot_command("fastboot devices", "检查Fastboot设备"):
        print("[错误] 未检测到设备,请确保设备处于Fastboot模式")
        return False
    
    # 2. 刷入各分区
    partitions = ["boot", "system", "vendor", "dtbo"]
    for part in partitions:
        img_path = os.path.join(images_dir, f"{part}.img")
        if os.path.exists(img_path):
            success = run_fastboot_command(
                f"fastboot flash {part} {img_path}",
                f"刷入{part}分区"
            )
            if not success:
                print(f"[警告] {part}分区刷入失败,继续执行...")
        else:
            print(f"[跳过] {part}.img 不存在,跳过此分区")
    
    # 3. 擦除数据
    run_fastboot_command("fastboot erase userdata", "擦除userdata")
    run_fastboot_command("fastboot erase cache", "擦除cache")
    
    # 4. 重启
    run_fastboot_command("fastboot reboot", "重启设备")
    
    print("=" * 50)
    print("  刷机完成!")
    print("=" * 50)
    return True

if __name__ == "__main__":
    # 使用示例
    flash_device("./images/")
小技巧:Python脚本中我加了时间戳和日志输出,这样刷机过程中出了什么问题,回头翻日志就能定位。我在项目中遇到过,刷到一半设备断连了,有日志就能知道是哪个步骤出的问题,不用从头再来。

Python脚本的进阶功能

上面那个是基础版。实际工作中,我还会加一些更实用的功能:

1. 多设备并行刷机

threading模块,可以同时刷多台设备。这在产线或者测试组非常有用。

import threading

def flash_device_thread(device_serial, images_dir):
    """为指定设备刷机"""
    cmd = f"fastboot -s {device_serial} flash boot {images_dir}/boot.img"
    # ... 其他命令

# 启动多个线程
devices = ["ABCD1234", "EFGH5678", "IJKL9012"]
threads = []
for serial in devices:
    t = threading.Thread(target=flash_device_thread, args=(serial, "./images/"))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

2. 刷机结果统计

刷完一批设备后,自动生成统计报告:

def generate_report(results):
    """生成刷机结果报告"""
    success = sum(1 for r in results if r["status"] == "success")
    failed = sum(1 for r in results if r["status"] == "failed")
    
    print(f"总设备数: {len(results)}")
    print(f"成功: {success}")
    print(f"失败: {failed}")
    print(f"成功率: {success/len(results)*100:.1f}%")
    
    # 输出失败设备列表
    if failed > 0:
        print("\n失败设备:")
        for r in results:
            if r["status"] == "failed":
                print(f"  - {r['serial']}: {r['error_msg']}")

脚本化刷机的核心流程

我把整个脚本化刷机的逻辑画了张图,方便你理解:

脚本化刷机核心流程 1. 准备镜像与脚本 2. 检查Fastboot设备 3. 解锁bootloader(可选) 4. 循环刷入各分区(boot/system/vendor...) 5. 擦除userdata/cache 6. 重启设备 关键说明 • 步骤3可根据需要跳过 • 步骤4支持断点续刷 • 每个步骤都有错误处理 • 日志记录每一步结果 • 支持多设备并行刷机 • 超时机制防止卡死 • 自动生成刷机报告

避坑指南

脚本化刷机虽然方便,但坑也不少。我把自己踩过的坑总结一下:

我曾经踩过的坑:
  • 路径问题:脚本里用了相对路径,换了个目录执行就找不到镜像了。后来我统一用绝对路径,或者在脚本开头先切换到脚本所在目录。
  • 设备断连:刷到一半USB线松了,脚本还在继续执行。现在我都会在关键步骤前后检查设备状态。
  • 超时问题:刷大分区(比如system有4GB)时,默认的超时时间不够。我一般设到120秒以上。
  • 权限问题:Linux/Mac下执行fastboot需要sudo权限,脚本里要提前处理。

总结

脚本化刷机,说白了就是把工程师从重复劳动中解放出来。批处理脚本适合简单的场景,Python脚本则能应对更复杂的需求。我个人建议,如果你只是偶尔刷一两台设备,批处理就够了;如果你需要管理多台设备、记录日志、生成报告,那还是上Python吧。

嗯,最后提醒一句:脚本写好了,一定要先在测试机上跑一遍。我见过有人直接在生产环境跑新脚本,结果把设备刷成砖了。小心驶得万年船,这话在刷机领域尤其适用。


公众号:蓝海资料掘金营,微信deep3321