解析sfdisk从python移动数据的进度

问题描述 投票:0回答:1

在我的 python 脚本中,我运行

subprocess.Popen("sfdisk...)
将包含所有数据的分区移动到右侧。它可以工作,但可能需要几分钟,而且我没有从 stdout/stderr 管道获得任何进度信息。

如果我从终端运行相同的命令,最后一行会显示进度,如

Moved 249856 from 249856 sectors (100%).
并且它正在更新,但是当我从 python 调用它时,我根本没有得到这一行。输出示例如下:

b'...\nData move:\n  start sector: (from/to) 2048 / 16000000\n  sectors: 249856\n  step size: 1048576 bytes'
b'The partition table has been altered.\nCalling ioctl() to re-read partition table.'

这里有什么方法可以强制

sfdisk
发送进度,即使是从 python 运行吗?或者我的代码有问题吗?完整代码如下:

read, write = os.pipe()
os.write(write, b"16000000")
os.close(write)
p = subprocess.Popen("/usr/sbin/sfdisk --move-data /dev/sda -N 1".split(" "),stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=read)
fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
fcntl.fcntl(p.stderr.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)

while True:
    output = p.stdout.read()
    error = p.stderr.read()
    if output == '' and error == '' and p.poll() is not None:
        break
    if output:
        print(output.strip())
    if error:
        print(error.strip())
python shell popen
1个回答
0
投票

最后,我通过使用

pty.openpty()
解决了这个问题。这是最终代码。这不是我最自豪的一段代码,它很狡猾,但它有效。

def sfdisk_update_partition(start=None, length=None, partition_number=None, print_output=False):
global status
global progress

if not partition_number:
    raise Exception("partition_number not specified")

progress = 0
status = STATUS.STARTED

master_fd, slave_fd = pty.openpty()

p = subprocess.Popen(f"/usr/sbin/sfdisk --move-data /dev/sda -N {partition_number}".split(" "), stdout=slave_fd, stderr=slave_fd, stdin=slave_fd, close_fds=True)
if start and length:
    os.write(master_fd, f"{start}, {length}\n".encode())
elif start:
    os.write(master_fd, f"{start}\n".encode())
elif length:
    os.write(master_fd, f", {length}\n".encode())
else:
    progress = 1
    status = STATUS.DONE

while True:
    output = os.read(master_fd,1024).decode()
    if not output and p.poll() is not None:
        break
    if output:
        if print_output:
            print(output)
        if "Do you want to write this to disk?" in output:
            os.write(master_fd, b"y\n")
        elif "Do you want to move partition data?" in output:
            os.write(master_fd, b"y\n")
        elif "Syncing disks" in output:
            break
        elif "sfdisk: start of the partition has not been moved; ignoring --move-data" in output:
            break
        elif "sfdisk: Use the --force flag to overrule all checks." in output:
            break
        else:
            r = re.search(r"Moved (.*?) from (.*?) sectors", output)
            if r:
                status = STATUS.RUNNING
                progress = float(r.groups()[0])/float(r.groups()[1])
progress = 1
status = STATUS.DONE
os.close(master_fd)
os.close(slave_fd)
time.sleep(2)
p.kill()
time.sleep(1)
© www.soinside.com 2019 - 2024. All rights reserved.