add gzip.py - RHEL6 version is too old
[compresslog.git] / zcatfollow
blobaa65790d965f3b0437300c3a5a85c45b0d2fd415
1 #!/usr/bin/python
3 # Will uncompress a gzipped file in "streaming" mode,
4 # like `tail -b +0 -f ` would do.
6 # If you pass -n <int> parameter it will try to act like
7 # a smart "tail" command: reads until the end of the current
8 # file, shows you the last <int> lines, then "follows" the file.
10 # If the writer is writing faster than we read, then it may never
11 # "detect" the "end of the file"...
13 # License: GPLv2
14 # Author: Martin Langhoff <martin.langhoff@gmail.com>
15 # Copyright: Remote Learner US - http://www.remote-learner.net/
17 import sys
18 import gzip
19 import zlib
20 import time
21 import getopt
22 from collections import deque
23 import signal
25 try:
26 optslist, args = getopt.getopt(sys.argv[1:], "tn:")
27 opts={}
28 for k,v in optslist:
29 opts[k] = v
31 except getopt.GetoptError as err:
32 # print help information and exit:
33 print(err) # will print something like "option -a not recognized"
34 #usage()
35 sys.exit(2)
37 # lookbehind buffer, defined as a list
38 lbbuf=deque([])
39 buffering=False
40 bufferfull=False
42 if '-n' in opts:
43 buffering=True
44 lbbufsize=int(opts['-n'])
46 # tidy up - no errors on ctrl-C, etc
47 def sig_exit(signum, frame):
48 # this will prompt fh cleanup, etc
49 sys.exit(0)
50 signal.signal(signal.SIGHUP, sig_exit)
51 signal.signal(signal.SIGINT, sig_exit)
52 signal.signal(signal.SIGTERM, sig_exit)
54 f = gzip.open(args[0], 'r')
56 # while / readline() sidesteps magic input buffering
57 while 1:
58 try:
59 line = f.readline()
60 except IOError:
61 ## we ignore IOError("CRC check failed")
62 ## because we are reading an "unfinished"
63 ## gzip stream...
64 # line won't get unset if this triggers
65 line = None
67 if not line:
68 if f.closed:
69 break
70 if buffering:
71 # got to the current tail of it
72 # dump our lookbehind buffer, stop buffering
73 for buf_line in lbbuf:
74 sys.stdout.write(buf_line)
75 buffering=False
76 # internal gzip API use?
77 # f.decompress.flush()
78 time.sleep(0.1)
79 else:
80 if not buffering:
81 sys.stdout.write(line)
82 else:
83 if bufferfull:
84 lbbuf.popleft()
85 lbbuf.append(line)
86 else:
87 lbbuf.append(line)
88 if len(lbbuf) >= lbbufsize:
89 bufferfull=True