2013-03-04 64 views
1

我正在嘗試使用Python創建一個用Raspberry Pi成像CF卡的工具。破管 - 試圖在液晶顯示器上顯示dd的進度

我大部分工作,直到我用dd實現壓縮圖像。

當我嘗試將gzip的輸出流水至dd時,我失去了捅動dd流程並取得進展的能力。

我試圖使用多個子進程,但不斷得到損壞管道或沒有這樣的文件錯誤。

下面是我的代碼:

#!/usr/bin/env python 
from Adafruit_CharLCD import Adafruit_CharLCD 
import os 
import sys 
import time 
import signal 
from subprocess import Popen, PIPE 
lcd = Adafruit_CharLCD() 
lcd.begin(16,2) 
imgpth = '/home/pi/image/image_V11.img.gz' 
line0 = "" 
line1 = "" 
q = 0 
r = 0 
s = 0 

def lcdPrint(column, row, message, clear=False): 
    if (clear == True): 
     lcd.clear() 

    lcd.setCursor(column, row) 
    lcd.message(message) 

lcd.clear()     
lcdPrint(0, 0, 'Preparing Copy', True) 
lcdPrint(0, 1, '') 

gz = Popen(['gunzip -c /home/pi/image/image_V11.img.gz'], stdout=PIPE) 
dd = Popen(['dd of=/dev/sda'],stdin=gz.stdout, stderr=PIPE)      

filebyte = os.path.getsize(imgpth)         
flsz = filebyte/1024000 

while dd.poll() is None:           
    time.sleep(1) 
    dd.send_signal(signal.SIGUSR1) 
    while 1:            
     l = dd.stderr.readline() 
    if '(' in l:            
     param, value = l.split('b',1)       
     line1 = param.rstrip()        
     r = float(line1)          
     s = r/1024000 
     break 
lcdPrint(0, 0, 'Copying....', True) 
q = round(s/flsz*100, 2)         
per = str(q)   

lcdPrint(0, 1, per + '% Complete',) 

lcdPrint(0, 0, 'Copy Complete', True) 
time.sleep(1) 
exit() 

我怎樣才能解決這個問題?

+0

你可以將'gzip'的輸出寫入一個文件,這樣你就不再輸入'dd'的輸入了嗎? – Gabe 2013-03-04 02:02:47

+0

我可以但受限於尺寸,我只有PI中的4GB SD卡,提取的dd映像文件爲16GB,壓縮後的映像僅爲1.5GB。所以我需要能夠在飛行中解壓縮。 – user2118325 2013-03-04 02:19:18

+0

'while 1'附近的縮進是錯誤的。檢查SIGUSR1不會殺死'dd'(它不應該)。在dd.stderr.readline()失敗後'dd.poll()'返回什麼? – jfs 2013-03-04 02:31:35

回答

0

我偶然發現了這個問題,因爲我的行爲完全一樣。我的完整的解決方案是在這裏:

我試着挑出之間我有什麼和你可能會顯示您的解決方案存在一些差異。

當啓動dd時,我將stderr和stdout重定向到管道。

dd = subprocess.Popen(['dd', 'of=/dev/sda', 'bs=1M'], bufsize=1, stdin=unzip.stdout, stdout=PIPE, stderr=STDOUT) 

我不認爲這應該真的有所作爲。你需要的一切應該去stderr,但由於某種原因,它似乎混合了我。

我使用一個單獨的線程從DD拾取輸出:

def read_pipe(out, queue): 
    for line in iter(out.readline, b''): 
     queue.put(str(line)) 
    out.close() 

dd_queue = queue.Queue() 
dd_thread = threading.Thread(target = read_pipe, args=(dd.stdout, dd_queue)) 
dd_thread.daemon = True 
dd_thread.start() 

然後當你調用:

dd.send_signal(signal.SIGUSR1) 

輸出被逮住的dd_queue。

我還發現一個gzip壓縮文件的未壓縮的大小存儲在最後4個字節:

fl = open(str(imgpath), 'rb') 
fl.seek(-4, 2) 
r = fl.read() 
fl.close() 
size = struct.unpack('<I', r)[0] 

os.path.getsize(imgpth)只會給你壓縮後的大小,因此百分比計算將是錯的。

相關問題