我最近开发了一个Python脚本,以利用工具通过JMX从JVM中检索指标。父进程(p1
)使用以下代码启动另一个进程(p2
)。
p2 = subprocess.Popen(
['java', '-jar', '/path/to/jmxterm-1.0-alpha-4-uber.jar',
'-l', url, '-u', username, '-p', password],
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
p2
启动并运行后,p1
进入一个非常长的循环,在其中执行以下三项操作:
p2
; p2.stdin.write()
发送查询
p2.stdout.readline()
来读取结果。问题:
p1
并返回终端,一切正常。如果我等到p1
完成长循环并退出,终端可以正常工作,除了我输入的所有字符都无法再看到。例如,如果我输入'ls',我在屏幕上看不到任何内容。但是当我点击 Return 时,我仍然可以看到像往常一样列出的文件和子目录。我的问题是,幕后会发生什么?如果我删除stderr = subprocess.PIPE
,jmxterm打印到stderr
的帮助消息将转到终端。因为他们搞砸了我脚本的输出,所以我试图改变
['java', '-jar', '/path/to/jmxterm-1.0-alpha-4-uber.jar', '-l', url,
'-u', username, '-p', password]
到
['java', '-jar', '/path/to/jmxterm-1.0-alpha-4-uber.jar', '-l', url,
'-u', username, '-p', password, '2>/dev/null']
但没有任何改变(帮助消息仍然发送到终端)。然后我将stderr = subprocess.PIPE
添加回我的脚本并启动一个守护程序线程以从stderr
读取并丢弃它所读取的内容。令我惊讶的是,守护程序线程从stderr
中读取任何内容。我完全迷失了。如果你有线索,请帮我一把。
供您参考,代码粘贴在下面:
from Queue import Queue
class JmxD(Detector):
def __init__(self, myId, jmxUrl, username, password):
super(JmxD, self).__init__(myId)
self.__jmxUrl = jmxUrl
self.__username = username
self.__password = password
# Start JMX terminal
self.__jmxTerm = subprocess.Popen(
['java', '-jar', jmxTermPath,
'-l', jmxUrl, '-u', username, '-p', password],
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
# Start two daemon threads to read from JMX terminal's stdout & stderr
def _stream2Queue(out, queue):
for line in iter(out.readline, ''):
line = line.strip()
if line:
queue.put(line)
out.close()
def _stream2Null(out):
for line in iter(out.readline, ''):
#print 'A line read from stderr: %s' % line.strip()
pass
out.close()
self.__queue = Queue()
self.__reader = Thread(target=_stream2Queue,
args=(self.__jmxTerm.stdout, self.__queue))
self.__reader.setDaemon(True) # This thread dies with the program
self.__reader.start()
self.__discarder = Thread(target=_stream2Null,
args=(self.__jmxTerm.stderr))
self.__discarder.setDaemon(True) # This thread dies with the program
self.__discarder.start()