瀏覽代碼

Initial ftail implementation

master
Dirk Alders 1 年之前
父節點
當前提交
00d7c6dd42
共有 5 個檔案被更改,包括 154 行新增0 行删除
  1. 6
    0
      .gitmodules
  2. 1
    0
      console_bottombar
  3. 68
    0
      ftail.py
  4. 78
    0
      tail.py
  5. 1
    0
      task

+ 6
- 0
.gitmodules 查看文件

@@ -0,0 +1,6 @@
1
+[submodule "console_bottombar"]
2
+	path = console_bottombar
3
+	url = https://git.mount-mockery.de/pylib/console_bottombar.git
4
+[submodule "task"]
5
+	path = task
6
+	url = https://git.mount-mockery.de/pylib/task.git

+ 1
- 0
console_bottombar

@@ -0,0 +1 @@
1
+Subproject commit c9d7f78f6d0feeeb5e14e4ca6a8ca22ce1c81165

+ 68
- 0
ftail.py 查看文件

@@ -0,0 +1,68 @@
1
+import argparse
2
+from console_bottombar import BottomBar
3
+import os
4
+import re
5
+import sys
6
+import tail
7
+import task
8
+
9
+VERSION = "0.1.0"
10
+
11
+HELPTEXT = """
12
+F1: Get this help message
13
+F2: Set a filter (regular expression) for the topic of a message
14
+    Examples:
15
+    * "/gfw/.*/main_light/" to get everything with "/gfw/" before "/main_light/"
16
+    * "^zigbee.*(?>!logging)$" to get everything starting with "zigbee" and not ending with "logging"
17
+    * "^(?!shellies).*/dirk/.*temperature$" to get everything not starting with "shellies" followed by "/dirk/" and ends with "temperature"
18
+F12: Quit ftail
19
+
20
+'c': Clear screen
21
+'q': Quit
22
+"""
23
+
24
+
25
+def tail_parser(line):
26
+    global my_bb
27
+
28
+    try:
29
+        match = len(re.findall(my_bb.get_entry('msg_re'), line)) > 0
30
+    except re.error:
31
+        print('No valid regular expression (%s). No filter active.' % my_bb.get_entry('msg_re'))
32
+        match = True
33
+
34
+    if match:
35
+        sys.stdout.write(line)
36
+
37
+
38
+if __name__ == "__main__":
39
+    parser = argparse.ArgumentParser(description='This is a mqtt sniffer.')
40
+    parser.add_argument('logfile')  # , nargs='+' for >= 1
41
+
42
+    args = parser.parse_args()
43
+
44
+
45
+    if not os.access(args.logfile, os.R_OK):
46
+        print("Error: File %s is not readable!" % logfile)
47
+        sys.exit(1)
48
+    else:
49
+
50
+        #
51
+        # Background tail task
52
+        #
53
+        tp = tail.Tail(args.logfile)
54
+        tp.register_callback(tail_parser)
55
+        my_tail = task.delayed(0.1, tp.follow, 0.1)
56
+
57
+        #
58
+        # Bottombar
59
+        #
60
+        my_bb = BottomBar(VERSION, label='ftail')
61
+        my_bb.add_entry('help', 1, my_bb.FUNC_INFO, '[F1] Help', infotext=HELPTEXT)
62
+        my_bb.add_entry('msg_re', 2, my_bb.FUNC_TEXT, label='[F2] Filter', default="")
63
+        my_bb.add_entry('quit', 12, my_bb.FUNC_QUIT, "Quit", label='[F12]', right=True)
64
+
65
+        my_tail.run()
66
+        my_bb.run()
67
+
68
+        my_tail.stop()

+ 78
- 0
tail.py 查看文件

@@ -0,0 +1,78 @@
1
+#!/usr/bin/env python
2
+
3
+'''
4
+Python-Tail - Unix tail follow implementation in Python. 
5
+
6
+python-tail can be used to monitor changes to a file.
7
+
8
+Example:
9
+    import tail
10
+
11
+    # Create a tail instance
12
+    t = tail.Tail('file-to-be-followed')
13
+
14
+    # Register a callback function to be called when a new line is found in the followed file. 
15
+    # If no callback function is registered, new lines would be printed to standard out.
16
+    t.register_callback(callback_function)
17
+
18
+    # Follow the file with 5 seconds as sleep time between iterations. 
19
+    # If sleep time is not provided 1 second is used as the default time.
20
+    t.follow(s=5) '''
21
+
22
+# Author - Kasun Herath <kasunh01 at gmail.com>
23
+# Source - https://github.com/kasun/python-tail
24
+
25
+import os
26
+import sys
27
+import time
28
+
29
+class Tail(object):
30
+    ''' Represents a tail command. '''
31
+    def __init__(self, tailed_file):
32
+        ''' Initiate a Tail instance.
33
+            Check for file validity, assigns callback function to standard out.
34
+            
35
+            Arguments:
36
+                tailed_file - File to be followed. '''
37
+
38
+        self.check_file_validity(tailed_file)
39
+        self.tailed_file = tailed_file
40
+        self.callback = sys.stdout.write
41
+
42
+    def follow(self, s=1):
43
+        ''' Do a tail follow. If a callback function is registered it is called with every new line. 
44
+        Else printed to standard out.
45
+    
46
+        Arguments:
47
+            s - Number of seconds to wait between each iteration; Defaults to 1. '''
48
+
49
+        with open(self.tailed_file) as file_:
50
+            # Go to the end of file
51
+            file_.seek(0,2)
52
+            while True:
53
+                curr_position = file_.tell()
54
+                line = file_.readline()
55
+                if not line:
56
+                    file_.seek(curr_position)
57
+                    time.sleep(s)
58
+                else:
59
+                    self.callback(line)
60
+
61
+    def register_callback(self, func):
62
+        ''' Overrides default callback function to provided function. '''
63
+        self.callback = func
64
+
65
+    def check_file_validity(self, file_):
66
+        ''' Check whether the a given file exists, readable and is a file '''
67
+        if not os.access(file_, os.F_OK):
68
+            raise TailError("File '%s' does not exist" % (file_))
69
+        if not os.access(file_, os.R_OK):
70
+            raise TailError("File '%s' not readable" % (file_))
71
+        if os.path.isdir(file_):
72
+            raise TailError("File '%s' is a directory" % (file_))
73
+
74
+class TailError(Exception):
75
+    def __init__(self, msg):
76
+        self.message = msg
77
+    def __str__(self):
78
+        return self.message

+ 1
- 0
task

@@ -0,0 +1 @@
1
+Subproject commit af35e83d1f07fd4cb9070bdb77cf1f3bdda3a463

Loading…
取消
儲存