-
Notifications
You must be signed in to change notification settings - Fork 10
/
runner.py
84 lines (67 loc) · 3.01 KB
/
runner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
from twisted.internet import reactor, protocol
from autobahn.websocket import WebSocketServerFactory, \
WebSocketServerProtocol, \
listenWS
from twisted.python.log import startLogging, msg
import sys
startLogging(sys.stdout)
# Examples:
# runner.py /bin/sh -c "tail -f /var/log/nginx/access.log | grep -v secret_admin_page" --line-buffered | awk '{\$1=\"\"; print}'"
# runner.py tail tail -F /var/log/nginx/access.log
COMMAND_NAME = sys.argv[1]
COMMAND_ARGS = sys.argv[1:]
LOCAL_ONLY = False
DEBUG = True
class ProcessProtocol(protocol.ProcessProtocol):
""" I handle a child process launched via reactor.spawnProcess.
I just buffer the output into a list and call WebSocketProcessOutputterThingFactory.broadcast when
any new output is read
"""
def __init__(self, websocket_factory):
self.ws = websocket_factory
self.buffer = []
def outReceived(self, message):
self.ws.broadcast(message)
self.buffer.append(message)
self.buffer = self.buffer[-10:] # Last 10 messages please
def errReceived(self, data):
print "Error: %s" % data
# http://autobahn.ws/python
class WebSocketProcessOutputterThing(WebSocketServerProtocol):
""" I handle a single connected client. We don't need to do much here, simply call the register and un-register
functions when needed.
"""
def onOpen(self):
self.factory.register(self)
for line in self.factory.process.buffer:
self.sendMessage(line)
def connectionLost(self, reason):
WebSocketServerProtocol.connectionLost(self, reason)
#super(WebSocketProcessOutputterThing, self).connectionLost(self, reason)
self.factory.unregister(self)
class WebSocketProcessOutputterThingFactory(WebSocketServerFactory):
""" I maintain a list of connected clients and provide a method for pushing a single message to all of them.
"""
protocol = WebSocketProcessOutputterThing
def __init__(self, *args, **kwargs):
WebSocketServerFactory.__init__(self, *args, **kwargs)
#super(WebSocketProcessOutputterThingFactory, self).__init__(self, *args, **kwargs)
self.clients = []
self.process = ProcessProtocol(self)
reactor.spawnProcess(self.process,COMMAND_NAME, COMMAND_ARGS, {}, usePTY=True)
def register(self, client):
msg("Registered client %s" % client)
if not client in self.clients:
self.clients.append(client)
def unregister(self, client):
msg("Unregistered client %s" % client)
if client in self.clients:
self.clients.remove(client)
def broadcast(self, message):
for client in self.clients:
client.sendMessage(message)
if __name__ == "__main__":
print "Running process %s with args %s" % (COMMAND_NAME, COMMAND_ARGS)
factory = WebSocketProcessOutputterThingFactory("ws://%s:9000" % ("localhost" if LOCAL_ONLY else "0.0.0.0"), debug=False)
listenWS(factory)
reactor.run()