暗无天日

=============>DarkSun的个人博客

如何通过shell找到SDCard的设备路径

玩OrangePi经常要写镜像到SD Card中,每次都手工寻找SD Card在 /dev/ 下的设备路径太麻烦,就想着用shell脚本来自动寻找。

在网上找了一下,在 https://www.enricozini.org/blog/2019/himblick/locating-a-sd-card/ 上发现了一个Python脚本可以自动定位 SD Card的路径:

def locate(self) -> Dict[str, Any]:
    """
    Locate the SD card to work on

    :returns: the lsblk data structure for the SD device
    """
    res = subprocess.run(["lsblk", "-JOb"], text=True, capture_output=True, check=True)
    res = json.loads(res.stdout)
    devs = []
    for dev in res["blockdevices"]:
        if dev["rm"] and not dev["ro"] and dev["type"] == "disk" and dev["tran"] == "usb":
            devs.append(dev)
            log.info("Found %s: %s %s %s %s",
                     dev["path"], dev["vendor"], dev["model"], dev["serial"],
                     format_gb(int(dev["size"])))
    if not devs:
        raise Fail("No candidate SD cards found")
    if len(devs) > 1:
        raise Fail(f"{len(devs)} SD cards found")
    return devs[0]

大概看了一下,逻辑很简单,就是在 lsblk 的结构中找出 可移动的(rm)、非只读的(ro)、类型为磁盘而不是分区(type)、设备传输类型为usb(tran)的完整设备路径(path). (关于lsblk每一列的作用,可以用lsblk --help来查看) 感觉完全可以用纯shell来实现,于是花了点时间把它改写成shell脚本

function fail()
{
    echo "$@" >&2
    exit 1
}
function locating_sd_card()
{
    sd_cards="$(lsblk -JOb |jq '.blockdevices[]|select((.rm) and (.ro|not) and (.type == "disk") and (.tran == "usb"))|.path')"
    sd_cards_count="$(echo "${sd_cards}"|wc -l)"
    if [[ ${sd_cards_count} -ne 1 ]];then
        fail "${sd_cards_count} SD CARDS Found!"
    else
        echo "${sd_cards}"
    fi
}

再加上卸载分区和写镜像到SD卡的函数,就可以一键重置OrangePi了

function umount_sd_card()
{
    lsblk -JOb |jq '.blockdevices[]|select((.rm) and (.ro|not) and (.type == "disk") and (.tran == "usb"))|.children[].mountpoint'|grep -v '[SWAP]'|xargs umount
}

function write_image()
{
    image_file="$1"
    sd_card=$(locating_sd_card)
    umount_sd_card
    dd if="${image_file}" of="${sd_card}" bs=1M
}