3 import sys, os, getopt, subprocess, time, select
6 def __init__(self, hostname):
7 self.hostname = hostname
10 self.outbuf = bytearray()
11 self.errbuf = bytearray()
13 def gotline(self, buf, line):
14 if buf == self.outbuf:
15 sys.stdout.buffer.write(line + b"\n")
16 sys.stdout.buffer.flush()
17 elif buf == self.errbuf:
18 sys.stderr.buffer.write(line + b"\n")
19 sys.stderr.buffer.flush()
21 def handle(self, fp, buf):
24 if len(self.outbuf) > 0:
25 self.gotline(self.outbuf, self.outbuf)
26 if len(self.errbuf) > 0:
27 self.gotline(self.errbuf, self.errbuf)
30 sys.stderr.write("loctail: disconnected from %s\n" % self.hostname)
36 self.gotline(buf, buf[:p])
40 self.handle(self.proc.stdout, self.outbuf)
42 self.handle(self.proc.stderr, self.errbuf)
45 self.proc = subprocess.Popen(["ssh", self.hostname, "tail", "-F", "/var/log/syslog"],
46 bufsize=0, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
47 self.lastconn = time.time()
50 if self.proc is not None:
58 if ret is None or (arg is not None and arg < ret):
69 if host.proc is not None:
70 rfd.append(host.proc.stdout)
71 rfd.append(host.proc.stderr)
73 to = min2(to, host.lastconn + 10)
74 rfd, wfd, efd = select.select(rfd, [], [], None if to is None else max(to - time.time(), 0))
78 if host.proc is not None:
79 if host.proc.stdout in rfd:
81 elif host.proc.stderr in rfd:
84 if now > host.lastconn + 10:
86 except KeyboardInterrupt:
91 out.write("usage: logtail [-h] HOST...\n")
93 opts, args = getopt.getopt(sys.argv[1:], "h")
102 hosts = [host(arg) for arg in args]