-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathzcatfollow
executable file
·94 lines (84 loc) · 2.13 KB
/
zcatfollow
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
85
86
87
88
89
90
91
92
#!/usr/bin/python
#
# Will uncompress a gzipped file in "streaming" mode,
# like `tail -b +0 -f ` would do.
#
# If you pass -n <int> parameter it will try to act like
# a smart "tail" command: reads until the end of the current
# file, shows you the last <int> lines, then "follows" the file.
#
# If the writer is writing faster than we read, then it may never
# "detect" the "end of the file"...
#
# License: BSD
# Author: Martin Langhoff <[email protected]>
#
import sys
import gzip
import zlib
import time
import getopt
from collections import deque
import signal
try:
optslist, args = getopt.getopt(sys.argv[1:], "tn:")
opts={}
for k,v in optslist:
opts[k] = v
except getopt.GetoptError as err:
# print help information and exit:
print(err) # will print something like "option -a not recognized"
#usage()
sys.exit(2)
# lookbehind buffer, defined as a list
lbbuf=deque([])
buffering=False
bufferfull=False
if '-n' in opts:
buffering=True
lbbufsize=int(opts['-n'])
# tidy up - no errors on ctrl-C, etc
def sig_exit(signum, frame):
# this will prompt fh cleanup, etc
sys.exit(0)
signal.signal(signal.SIGHUP, sig_exit)
signal.signal(signal.SIGINT, sig_exit)
signal.signal(signal.SIGTERM, sig_exit)
f = gzip.open(args[0], 'r')
# while / readline() sidesteps magic input buffering
while 1:
try:
line = f.readline()
except IOError:
## we ignore IOError("CRC check failed")
## because we are reading an "unfinished"
## gzip stream...
# line won't get unset if this triggers
line = None
if not line:
try:
if f.closed:
break
except AttributeError:
# old gzip does not have "closed"
pass
if buffering:
# got to the current tail of it
# dump our lookbehind buffer, stop buffering
for buf_line in lbbuf:
sys.stdout.write(buf_line)
buffering=False
# internal gzip API use?
# f.decompress.flush()
time.sleep(0.1)
else:
if not buffering:
sys.stdout.write(line)
else:
if bufferfull:
lbbuf.popleft()
lbbuf.append(line)
else:
lbbuf.append(line)
if len(lbbuf) >= lbbufsize:
bufferfull=True