我有三个交互式控制台应用程序:控制器,节点,客户端。
我无法处理超过两个!
以下脚本生成正确的输出。
spawn controller
expect "controller>"
spawn node
expect "node>"
虽然这个脚本没有。
spawn controller
expect "controller>"
spawn node
expect "node>"
spawn client
expect "client>"
从客户端的输出可以得出控制器不再运行的结论。
为什么呢?它为什么停止了?我该如何让它继续运行?
我尝试使用Python绑定。它也没用。
Python 2.7,Pexpect 3.0
UPDATE:python代码和输出
Python代码:
import pexpect
def pp(t, s):
t.expect(s)
print t.before + t.after
r = pexpect.spawn('bash ./registry.sh')
c = pexpect.spawn ('bash ./controller.sh')
pp(c, '>')
n = pexpect.spawn ('bash ./node.sh')
pp(n, '>')
cl = pexpect.spawn ('bash ./client.sh')
pp(cl, '>')
cl.sendintr()
n.sendintr()
c.sendintr()
r.sendintr()
输出:
INFO ds.controller.Main - Starting Controller
Nov 22, 2013 11:28:34 AM sun.rmi.server.UnicastServerRef logCall
FINER: RMI TCP Connection(1)-127.0.0.1: [127.0.0.1: sun.rmi.transport.DGCImpl[0:0:0, 2]: java.rmi.dgc.Lease dirty(java.rmi.server.ObjID[], long, java.rmi.dgc.Lease)]
INFO ds.controller.Main - Registered remote object
controller>
INFO ds.node.Main - Starting Node
INFO ds.node.Main - Base folder folders/node
INFO ds.node.Main - ServerSocket created
Nov 22, 2013 11:28:34 AM sun.rmi.server.UnicastServerRef logCall
FINER: RMI TCP Connection(1)-192.168.1.5: [192.168.1.5: sun.rmi.transport.DGCImpl[0:0:0, 2]: java.rmi.dgc.Lease dirty(java.rmi.server.ObjID[], long, java.rmi.dgc.Lease)]
INFO ds.node.Main - Registered remote object as NodeServer-1385116114787
INFO ds.node.Main - Created folder folders/node/NodeServer-1385116114787
DEBUG ds.node.Commands - Connected to controller
Nov 22, 2013 11:28:34 AM sun.rmi.server.UnicastServerRef logCall
FINER: RMI TCP Connection(2)-192.168.1.5: [192.168.1.5: sun.rmi.transport.DGCImpl[0:0:0, 2]: java.rmi.dgc.Lease dirty(java.rmi.server.ObjID[], long, java.rmi.dgc.Lease)]
Nov 22, 2013 11:28:34 AM sun.rmi.server.UnicastServerRef logCall
FINER: RMI TCP Connection(2)-192.168.1.5: [192.168.1.5: ds.node.rmi.NodeFileServerImpl[11d2b4e2:1427f5a9f6b:-7fff, -3656571857937916756]: public abstract java.lang.Integer ds.node.rmi.NodeFileServerInterface.getServerSocketPort() throws java.rmi.RemoteException]
INFO ds.node.rmi.NodeFileServerImpl - Start listening on ServerSocketPort
INFO ds.node.rmi.NodeFileServerImpl - Returning ServerSocketPort
DEBUG ds.shared.socket.ServerSocketHandler - Waiting for incomming connections
DEBUG ds.shared.socket.ServerSocketHandler - Accepted connection
DEBUG ds.shared.socket.ClientSocketHandler - Connection ID 0
DEBUG ds.shared.socket.ServerSocketHandler - Set clientHandler: ds.shared.socket.ClientSocketHandler@f31a3e3
node>
Traceback (most recent call last):
File "../expect/py.py", line 13, in <module>
pp(cl, '>')
File "../expect/py.py", line 4, in pp
t.expect(s)
File "build/bdist.macosx-10.9-intel/egg/pexpect/__init__.py", line 1410, in expect
File "build/bdist.macosx-10.9-intel/egg/pexpect/__init__.py", line 1425, in expect_list
File "build/bdist.macosx-10.9-intel/egg/pexpect/__init__.py", line 1527, in expect_loop
pexpect.TIMEOUT: Timeout exceeded.
<pexpect.spawn object at 0x10cd773d0>
version: 3.0
command: /bin/bash
args: ['/bin/bash', './client.sh']
searcher: <pexpect.searcher_re object at 0x10cd77390>
buffer (last 100 chars): 'ng, java.rmi.dgc.Lease)]\r\nINFO ds.client.Main - Registered remote object as Client-1385116115111\r\n'
before (last 100 chars): 'ng, java.rmi.dgc.Lease)]\r\nINFO ds.client.Main - Registered remote object as Client-1385116115111\r\n'
after: <class 'pexpect.TIMEOUT'>
match: None
match_index: None
exitstatus: None
flag_eof: False
pid: 2036
child_fd: 6
closed: False
timeout: 30
delimiter: <class 'pexpect.EOF'>
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
我认为这是因为子进程不是交错的。我应该使用非阻塞的东西吗?
答案 0 :(得分:1)
为什么?因为进程正在填充他们的std缓冲区并被阻止写入stdout。
工作代码。有足够的评论来解决问题的原因。
#!/usr/bin/python
import pexpect
import threading
import time
# Consumes output of some subprocess in a background thread
class OutletThread(threading.Thread):
# obj: pexpect.spawn object
# delay: time (in seconds) to wait between two reads
def __init__(self, obj, delay = 1):
threading.Thread.__init__(self)
self.obj = obj
self.on = True
self.delay = delay
# main
def run(self):
while self.on:
try:
self.obj.read_nonblocking(size=2048, timeout=0)
except pexpect.TIMEOUT:
pass
time.sleep(self.delay)
# Brief
# Print expected output
# Arguments
# obj: pexpect.spawn object
# s: expected string
# Exceptions
# pexpect.TIMEOUT if default timeout is not met
def pp(obj, s):
obj.expect(s)
print obj.before + obj.after
print("Setting up the environment...")
print("Registry...")
r = pexpect.spawn('./registry.sh')
# Hold a moment for Java RMI Registry to start.
# So that controller can connect properly.
time.sleep(1)
print("Controller...")
c = pexpect.spawn ('./controller.sh')
pp(c, '>')
c_rlt = OutletThread(c)
c_rlt.start()
print("Node...")
n = pexpect.spawn ('./node.sh')
pp(n, '>')
n_rlt = OutletThread(n)
n_rlt.start()
print("Client...")
cl = pexpect.spawn ('./client.sh')
pp(cl, '>')
cl_rlt = OutletThread(cl)
cl_rlt.start()
raw_input("Press Enter to run 'info' at the controller...")
# Disable controller outlet
c_rlt.on = False
# Run command
c.sendline('info')
# Expect output
pp(c, '>')
# Enable controller outlet
c_rlt.on = True
raw_input("Press Enter to exit...")
# Disable and join all outlet threads
c_rlt.on = False
c_rlt.join()
n_rlt.on = False
n_rlt.join()
cl_rlt.on = False
cl_rlt.join()
# Terminate all spawned processes
cl.sendintr()
n.sendintr()
c.sendintr()
r.sendintr()
<强>输出强>
Setting up the environment...
Registry...
Controller...
INFO ds.controller.Main - Starting Controller
INFO ds.controller.Main - Registered remote object
controller>
Node...
INFO ds.node.Main - Starting Node
INFO ds.node.Main - Base folder folders/node
INFO ds.node.Main - ServerSocket created
INFO ds.node.Main - Registered remote object as NodeServer-1385415881716
INFO ds.node.Main - Created folder folders/node/NodeServer-1385415881716
DEBUG ds.node.Commands - Connected to controller
INFO ds.node.rmi.NodeFileServerImpl - Start listening on ServerSocketPort
INFO ds.node.rmi.NodeFileServerImpl - Returning ServerSocketPort
DEBUG ds.shared.socket.ServerSocketHandler - Waiting for incomming connections
DEBUG ds.shared.socket.ServerSocketHandler - Accepted connection
DEBUG ds.shared.socket.ClientSocketHandler - Connection ID 0
DEBUG ds.shared.socket.ServerSocketHandler - Set clientHandler: ds.shared.socket.ClientSocketHandler@a9c8620
node>
Client...
INFO ds.client.Main - Starting Client
INFO ds.client.Main - Base folder folders/client
INFO ds.client.Main - Registered remote object as Client-1385415882026
DEBUG ds.client.Commands - Connected to controller.
DEBUG ds.client.Commands - Connecting to 192.168.1.8:50690
DEBUG ds.client.Commands - Opened socket connection.
client>
Press Enter to run 'info' at the controller...
info
DS Controller, version 0.1 (Beta)
Connected nodes:
* NodeServer-1385415881716
controller>
Press Enter to exit...
Fedors-MacBook-Pro:distributed ted$ ../expect/nv.py
Setting up the environment...
Registry...
Controller...
INFO ds.controller.Main - Starting Controller
INFO ds.controller.Main - Registered remote object
controller>
Node...
INFO ds.node.Main - Starting Node
INFO ds.node.Main - Base folder folders/node
INFO ds.node.Main - ServerSocket created
INFO ds.node.Main - Registered remote object as NodeServer-1385417858283
INFO ds.node.Main - Created folder folders/node/NodeServer-1385417858283
DEBUG ds.node.Commands - Connected to controller
INFO ds.node.rmi.NodeFileServerImpl - Start listening on ServerSocketPort
INFO ds.node.rmi.NodeFileServerImpl - Returning ServerSocketPort
DEBUG ds.shared.socket.ServerSocketHandler - Waiting for incomming connections
DEBUG ds.shared.socket.ServerSocketHandler - Accepted connection
DEBUG ds.shared.socket.ClientSocketHandler - Connection ID 0
DEBUG ds.shared.socket.ServerSocketHandler - Set clientHandler: ds.shared.socket.ClientSocketHandler@1d672476
node>
Client...
INFO ds.client.Main - Starting Client
INFO ds.client.Main - Base folder folders/client
INFO ds.client.Main - Registered remote object as Client-1385417858595
DEBUG ds.client.Commands - Connected to controller.
DEBUG ds.client.Commands - Connecting to 192.168.1.8:50883
DEBUG ds.client.Commands - Opened socket connection.
client>
Press Enter to run 'info' at the controller...
info
DS Controller, version 0.1 (Beta)
Connected nodes:
* NodeServer-1385417858283
controller>
Press Enter to exit...
<强>资产。强>
<强>链接。强>
非常感谢Thomas Kluyver ,其他pexpect爱好者和stackoverflow团队。