#!/usr/bin/env python
#coding=utf-8
import os
import fcntl
import select, sys, subprocess
vmstat_pipe = subprocess.Popen('netstat', shell=True, bufsize=1024,
stdout=subprocess.PIPE).stdout
iostat_pipe = subprocess.Popen('top', shell=True, bufsize=1024,
stdout=subprocess.PIPE).stdout
上面是通用代码,下面会分别用select,poll,epoll来进行读管道的数据
1.select
while 1:
infds,outfds,errfds = select.select([vmstat_pipe,iostat_pipe],[],[],5000)
if len(infds) != 0:
for m in infds:
msg = m.readline()
print "Get ", msg, "from pipe", m
2.poll
pipe_dict = {vmstat_pipe.fileno():vmstat_pipe, iostat_pipe.fileno():iostat_pipe}
p = select.poll()
p.register(vmstat_pipe, select.POLLIN|select.POLLERR|select.POLLHUP)
p.register(iostat_pipe, select.POLLIN|select.POLLERR|select.POLLHUP)
while 1:
result = p.poll(5000)
if len(result) != 0:
for m in result:
if m[1] & select.POLLIN:
print "Get", pipe_dict[m[0]].readline(), "from pipe", m[0]
3.epoll
与poll的代码基本一致,只是改为epoll即可:p = select.epoll()
阻塞与非阻塞:
注意上例中都是用的readline(),而没有用read(),原因是用read()会导致阻塞,读不到数据;如果想要用read(),那么
需要设置管道为非阻塞的:
fl = fcntl.fcntl(vmstat_pipe.fileno(), fcntl.F_GETFL)
fcntl.fcntl(vmstat_pipe.fileno(), fcntl.F_SETFL, fl | os.O_NONBLOCK)
fl = fcntl.fcntl(iostat_pipe.fileno(), fcntl.F_GETFL)
fcntl.fcntl(iostat_pipe.fileno(), fcntl.F_SETFL, fl | os.O_NONBLOCK)
另外如果管道的写端关闭,会读到一个文件结束符,比如上面代码的vmstat_pipe管道写端关闭后,会一直读到文件