在我的 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())
最后,我通过使用
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)