2017-02-02 79 views
1

如果我使用dd將* .img文件恢復到SD卡,它沒有問題。如果我在dd完成後立即嘗試安全地刪除(彈出鸚鵡螺)SD卡,會彈出一條通知:「正在寫入SD卡」。讀卡器上的LED也閃爍。需要幾分鐘時間才能取出卡。第一個問題是,這怎麼可能?dd圖像SD卡完成,SD卡仍然忙

我在bash腳本中使用dd。一旦腳本完成,應該可以取出SD卡。第二個問題是,我能否以某種方式檢查SD卡的狀態,即是否忙?

編輯20170203: 這是腳本。目的只是爲了恢復樹莓派的備份。

#!/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 

感謝

+0

你能告訴我們你的腳本嗎? –

+0

簡單的答案是運行'sync',並等待它在移除設備之前退出。 (更直接的,可以在塊設備上調用'fsync()'系統調用)。 –

+0

順便說一句,你有一些錯誤的引號等錯誤的錯誤; http://shellcheck.net/會找到它們。你可能想''恢復到路徑:\「$ DEV \」「'使內部引號文字而不是語法。並且全大寫變量名稱用於對OS或shell有意義的變量,而具有至少一個小寫字符的名稱則保留給應用程序使用;請參閱http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html –

回答

2

fsync()系統調用會造成在操作系統級別的任何寫入緩存被刷新。雖然可以使用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 
+0

謝謝你。有用! – mrremo

0

可如果事情是使用該設備使用lsof。如果你的SD卡被認定爲/dev/sdd

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

lsof不適用於我。讀卡器仍然閃爍,鸚鵡螺不能讓我取出卡。 – mrremo

+0

這個答案根本不對。它告訴我們是否有文件是打開的,但是它並不告訴你塊緩存是否有未刷新的寫操作,這是在「dd」完成後OP仍處於使用狀態。 –

+0

也許你應該寫一個答案來使用「同步」。 – mgor

1

我建議你使用此處描述這種非常快速的perl腳本:https://askubuntu.com/a/216628

我用我自己有時太找到讓資源忙碌的不需要/隱藏/未知進程。

一旦你得到了這個過程,就可以調查保持SSD繁忙的內在行爲。

+1

不,如果這是問題,由於該腳本使用內核的虛擬內存塊轉儲機制,即使它們在內核中處於待定狀態,您仍然會看到寫入操作。 – Defrag

+0

你是對的 - 我對機制做了一個毫無根據的假設。對此抱歉。 –