我正在尝试使用Python创建一个使用Raspberry Pi为CF卡成像的工具。
在我使用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 :(得分: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)只会给你压缩的大小,所以百分比计算是错误的。