2017-03-22 8 views
0

クライアントがWebSocketのを接続して、方法tail_log呼び出して、新しいクライアントがあなたの無限ループが背中に制御を得なければなりませんどのようにこの問題を解決するために無限ループは、WebSocketのサーバー

def on_message(self, message): 

    def tail_log(user,ip,port,cmd,log_path,url): 
     cmd = "/usr/bin/ssh -p {port} {user}@{ipaddr} {command} {logpath}" \ 
      .format(user=user, ipaddr=ip, port=port, command=cmd, logpath=log_path) 
     f = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) 

     while True: 
      line = f.stdout.readline().strip() 
      if line == '': 
       self.write_message('failed') 
       break 
      self.write_message(line) 

    tail_log(user=SSH_USER,ip=IP_ADDR,cmd=CMD,port=SSH_PORT,log_path=LOG_PATH,url=SOCKET_URL) 

答えて

0

を接続することはできません接続することはできませんTornadoのイベントループは、yieldawait、またはtail_log関数から戻ることによって実行されます。無限ループはイベントループに対して制御をもたらさないため、イベントループは新しいWebソケット接続を含むこれ以上のイベントを処理できません。

Tornado's own process moduleを使用して、サブプロセスのstdoutから非同期に読み取ります。

import tornado.ioloop 
import tornado.process 
import tornado.web 
import tornado.websocket 


class TailHandler(tornado.websocket.WebSocketHandler): 
    def open(self): 
     self.write_message(u"Tailing....") 
     self.p = tornado.process.Subprocess(
      "tail -f log.log", 
      stdout=tornado.process.Subprocess.STREAM, 
      stderr=tornado.process.Subprocess.STREAM, 
      shell=True) 

     tornado.ioloop.IOLoop.current().add_callback(
      lambda: self.tail(self.p.stdout)) 

     tornado.ioloop.IOLoop.current().add_callback(
      lambda: self.tail(self.p.stderr)) 

     self.p.set_exit_callback(self.close) 

    async def tail(self, stream): 
     try: 
      while True: 
       line = await stream.read_until(b'\n') 
       if line: 
        self.write_message(line.decode('utf-8')) 
       else: 
        # "tail" exited. 
        return 
     except tornado.iostream.StreamClosedError: 
      # Subprocess killed. 
      pass 
     finally: 
      self.close() 

    def on_close(self): 
     # Client disconnected, kill the subprocess. 
     self.p.proc.kill() 


class MainHandler(tornado.web.RequestHandler): 
    def get(self): 
     self.write("""<html><head><script> 
     var ws = new WebSocket("ws://localhost:8888/tail"); 
ws.onmessage = function (evt) { 
    document.write('<p>' + evt.data + '</p>'); 
};</script></head></html>""") 


def make_app(): 
    return tornado.web.Application([ 
     (r"/", MainHandler), 
     (r"/tail", TailHandler), 
    ]) 


app = make_app() 
app.listen(8888) 
tornado.ioloop.IOLoop.current().start() 

あなたはまだPythonの3.5でない場合は、「非同期DEF」のgen.coroutine @代わり、「のawait」の代わりに「降伏」、および「リターン」の代わりに「休憩」:このような何か。

+0

ありがとう、私のコードでは、私のクエリサーバーのコンテンツがクライアントからの情報をアップロードするために、実装はメッセージモジュール上にあります – FreeEric