将图像添加到 SD 卡完成,SD 卡仍然忙

dd an image to SD card finished, SD card still busy

如果我使用 dd 将 *.img 文件恢复到 SD 卡,它可以正常工作。如果我在 dd 完成后立即尝试安全移除(在 nautilus 中弹出)SD 卡,则会弹出一条通知:"Something is writing to SD card"。卡 reader 上的 LED 也在闪烁。需要几分钟才能取出卡。第一个问题是,那怎么可能?

我在 bash 脚本中使用 dd。脚本完成后,应该可以移除 SD 卡。第二个问题是,我能否以某种方式检查 SD 卡的状态,是否忙?

编辑 20170203: 这是脚本。目的只是恢复 raspberry pi 备份。

#!/bin/bash
#
#enter path of image
IMG=$(whiptail --inputbox "Enter path to image." 8 78 "$HOME/Downloads/raspberry_backup.img.gz" --title "Name" 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus != 0 ]; then
    echo "INFO: User abort."
    exit 1
fi

#check for dependencies
if [ -z "$(which parted 2> /dev/null)" ] || [ -z "$(which gzip 2> /dev/null)" ]; then
    if (whiptail --title "Dependencies" --yesno "This script need parted and gzip. One or more are not installed. Install now?" 8 78) then
        sudo dnf install -y parted gzip
    else
        exit 1
    fi
fi

#show information of drives
whiptail --scrolltext --title "Info about mounted devices:" --msgbox "$(sudo parted -l -m init G print | grep /dev/sd | cut -d: -f1,2)" 8 78

#enter drive name
DEV=$(whiptail --inputbox "Enter Device Name." 8 78 /dev/sd --title "Device Name" 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus != 0 ]; then
    echo "INFO: User abort."
    exit 1
fi

#check for /dev/sd* vaidity
if [[ $DEV != "/dev/sd"* ]]; then
    echo "ERROR: ${DEV} is not valid."
    exit 1
fi

#if restore image is *.gz then uncomress first
if [[ "$IMG" == *".gz" ]]; then
    (pv -n ${IMG} | gzip -d -k > $HOME/raspberry_restore.img) 2>&1 | whiptail --gauge "Please wait while uncompressing image..." 6 50 0
    IMG=$HOME/raspberry_restore.img
fi

if [[ "$IMG" == *".img" ]]; then
    SIZEDD=$(sudo parted -m $IMG unit B print | grep ext4 | cut -d: -f3 | cut -dB -f1)
    (sudo dd if=$IMG bs=1M | pv -n --size $SIZEDD | sudo dd of=$DEV bs=1M) 2>&1 | whiptail --gauge "Please wait while restoring image to SD card..." 6 50 0
else
    echo "ERROR: Not an *.img file"
    exit 1
fi

sudo rm $HOME/raspberry_restore.img

#show information
whiptail --title "Restore finished." --msgbox "Restored to path: "$DEV"" 8 78
exit 1

谢谢

如果有人正在使用设备,您可以使用 lsof。如果您的 SD 卡被识别为 /dev/sdd:

lsof /dev/sdd 2>/dev/null && echo "device is busy"

fsync() 系统调用将导致刷新 OS 级别的任何写入缓存。虽然可以用 C 编写一些东西来为手头的特定块设备调用它,但从 shell 开始,在 shell 中最简单的方法是使用 sync 命令刷新所有跨所有文件系统和设备的待处理写入:

sync

或者,您可以告诉 dd 使用 O_SYNC 标志,通过传递 oflag=sync,防止 dd 退出,直到写入持久化到磁盘:

# note that oflag is a GNU extension, not found on MacOS/BSD
dd oflag=nocache,sync of="$DEV" bs=1M

如果您知道 SD 卡的本机块大小,请考虑改用 O_DIRECT

# 4k is a reasonable guess on block size; tune based on your actual hardware.
dd oflag=direct of="$DEV" bs=4K

我建议您使用这里描述的这个非常快速的 perl 脚本:https://askubuntu.com/a/216628

我自己有时也会找到 unwanted/hidden/unknown 使资源繁忙的进程。

获得进程后,可以调查使 SSD 忙碌的内部行为。