#!/usr/bin/env python3 import sys import time import subprocess import select import re import argparse update_every = 0.001 log_path = '/var/log/' log_file = 'slapd' log_file_path = log_path + log_file rgx = dict() connections = dict() rgx['conn'] = re.compile(r'conn=(?P<conn>[0-9]+) .*?=.*? (?P<closed>closed)?') def sleep(start_time): """After hard work, take a nap""" current_time = time.perf_counter() elapsed_time = current_time - start_time sleep_time = update_every - elapsed_time if sleep_time > 0: time.sleep(sleep_time) def parse(line): """Parse line and print""" connect = rgx['connect'].search(line) if(connect): ip = connect.group('ip') port = connect.group('port') connection_id = connect.group('conn') if connection_id not in connections: connections[connection_id] = ip, port print(len(connections), ip, port, line, end='') else: conn = rgx['conn'].search(line) if(conn): connection_id = conn.group('conn') if connection_id in connections: ip, port = connections[connection_id] print(len(connections), ip, port, line, end='') if conn.group('closed'): del connections[connection_id] def tail_input(fin): """Open input file in tail mode""" poll = select.poll() poll.register(fin.stdout) try: while True: start_time = time.perf_counter() if poll.poll(1): line = fin.stdout.readline().decode('utf-8') parse(line) sleep(start_time) except KeyboardInterrupt: sys.stdout.flush() pass def read_input(fin): """Read from input file""" try: for line in fin: parse(line) except KeyboardInterrupt: sys.stdout.flush() pass def main(): """Open file in non blocking mode and parse it""" parser = argparse.ArgumentParser( add_help=False, description='Parse from file or stdin' ) parser.add_argument( '-f', '--follow', dest='follow', action='store_const', const=True, help='Output appended data as the file grows' ) parser.add_argument( 'pattern', type=str, help='Regex pattern' ) parser.add_argument( 'file', nargs='?', type=str, help='File to open' ) parser.add_argument( '-h', '--help', action='help', help='Show this help message and exit' ) arg = vars(parser.parse_args()) rgx['connect'] = re.compile(''.join([r'conn=(?P<conn>[0-9]+).+?ACCEPT from IP=(?P<ip>', arg['pattern'], r'):[0-9]+ \(IP=0\.0\.0\.0:(?P<port>[0-9]+)\)'])) if arg['follow']: if arg['file']: path = arg['file'] else: path = log_file_path fin = subprocess.Popen(['tail', '-F', path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) tail_input(fin) else: if arg['file']: with open(arg['file'], 'r') as fin: read_input(fin) else: fin = sys.stdin read_input(fin) sys.exit(0) if __name__ == '__main__': main() sys.exit(0)