将图像添加到 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 忙碌的内部行为。
如果我使用 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 忙碌的内部行为。