Expect无法生成两个以上的命令

时间:2013-11-20 21:08:19

标签: python multithreading expect python-multithreading pexpect

我有三个交互式控制台应用程序:控制器,节点,客户端。

我无法处理超过两个!

以下脚本生成正确的输出。

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

我认为这是因为子进程不是交错的。我应该使用非阻塞的东西吗?

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...

<强>资产。

  • Python 2.7.5
  • Pexpect 3.0
  • 线程和时间库

<强>链接。

非常感谢Thomas Kluyver ,其他pexpect爱好者和stackoverflow团队。