如何使用 Python 从 fio 捕获非阻塞实时输出
How to capture non-blocking realtime output from fio using Python
>>>x = subprocess.Popen(["fio", "--filename=/dev/sdd", "--name=job1", "--numjobs=2"], stdout=subprocess.PIPE)
但我需要实时捕捉 fio 进程。我虽然在做线程 subprocess.stdout.readline,但它似乎没有更新性能数据:
>>> x = subprocess.Popen(["fio", "--filename=/dev/sdd", "--name=job1", "--numjobs=2"], stdout=subprocess.PIPE)
>>> x.stdout.readline()
'job1: (g=0): rw=read, bs=4K-4K/4K-4K/4K-4K, ioengine=sync, iodepth=1\n'
>>> x.stdout.readline()
'...\n'
>>> x.stdout.readline()
'fio-2.2.11\n'
>>> x.stdout.readline()
'Starting 2 processes\n'
>>> x.stdout.readline()
它只是在这之后挂起。
fio 的命令行执行如下所示:
[root@goblinbank tmp]# fio --filename=/dev/sdd --name=job1 --numjobs=2
job1: (g=0): rw=read, bs=4K-4K/4K-4K/4K-4K, ioengine=sync, iodepth=1
...
fio-2.2.11
Starting 2 processes
Jobs: 2 (f=2): [R(2)] [0.2% done] [246.3MB/0KB/0KB /s] [63.5K/0/0 iops] [eta 02h:26m:09s]
"Jobs: 2 (f=2): [R(2)]"之后的文字不断刷新为新值
然后您可以使用 fcntl
将其设置为非阻塞 IO,如果数据不可读取,它将引发异常。只需添加:
fcntl.fcntl(process.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
创建流程后,使用 try
/except IOError
子句验证是否有可读内容,如下所示:
import fcntl
import os
import shlex
import subprocess
import time
cmd = 'fio --filename=/home/turicas/data/test.tmp --name=job1 --numjobs=2'
process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE)
fcntl.fcntl(process.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
data = None
while data != '':
try:
data = process.stdout.readline()
except IOError:
print 'no data. waiting...'
time.sleep(0.1) # wait stdout output to be available
else:
print 'data read:', data
print 'stdout closed'
这解决了问题:
x = subprocess.Popen(["fio", "--filename=/dev/sdd", "--name=job1", "--numjobs=2", "--eta=always"], stdout=subprocess.PIPE, universal_newlines=True)
注意 fio 中的 --eta=always
标志和 Popen 中的 universal_newlines=True
参数。
更多信息here。
>>>x = subprocess.Popen(["fio", "--filename=/dev/sdd", "--name=job1", "--numjobs=2"], stdout=subprocess.PIPE)
但我需要实时捕捉 fio 进程。我虽然在做线程 subprocess.stdout.readline,但它似乎没有更新性能数据:
>>> x = subprocess.Popen(["fio", "--filename=/dev/sdd", "--name=job1", "--numjobs=2"], stdout=subprocess.PIPE)
>>> x.stdout.readline()
'job1: (g=0): rw=read, bs=4K-4K/4K-4K/4K-4K, ioengine=sync, iodepth=1\n'
>>> x.stdout.readline()
'...\n'
>>> x.stdout.readline()
'fio-2.2.11\n'
>>> x.stdout.readline()
'Starting 2 processes\n'
>>> x.stdout.readline()
它只是在这之后挂起。
fio 的命令行执行如下所示:
[root@goblinbank tmp]# fio --filename=/dev/sdd --name=job1 --numjobs=2
job1: (g=0): rw=read, bs=4K-4K/4K-4K/4K-4K, ioengine=sync, iodepth=1
...
fio-2.2.11
Starting 2 processes
Jobs: 2 (f=2): [R(2)] [0.2% done] [246.3MB/0KB/0KB /s] [63.5K/0/0 iops] [eta 02h:26m:09s]
"Jobs: 2 (f=2): [R(2)]"之后的文字不断刷新为新值
然后您可以使用 fcntl
将其设置为非阻塞 IO,如果数据不可读取,它将引发异常。只需添加:
fcntl.fcntl(process.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
创建流程后,使用 try
/except IOError
子句验证是否有可读内容,如下所示:
import fcntl
import os
import shlex
import subprocess
import time
cmd = 'fio --filename=/home/turicas/data/test.tmp --name=job1 --numjobs=2'
process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE)
fcntl.fcntl(process.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
data = None
while data != '':
try:
data = process.stdout.readline()
except IOError:
print 'no data. waiting...'
time.sleep(0.1) # wait stdout output to be available
else:
print 'data read:', data
print 'stdout closed'
这解决了问题:
x = subprocess.Popen(["fio", "--filename=/dev/sdd", "--name=job1", "--numjobs=2", "--eta=always"], stdout=subprocess.PIPE, universal_newlines=True)
注意 fio 中的 --eta=always
标志和 Popen 中的 universal_newlines=True
参数。
更多信息here。