source: mythtv/mythtv/contrib/maintenance/logcleanup.py @ cd002d2bfb

devel/2020-playerdevel/ffmpeg-resyncdevel/gpu-commflagfixes/0.25fixes/0.26fixes/0.27fixes/0.28fixes/29fixes/30fixes/31github-templates
Last change on this file since cd002d2bfb was cd002d2bfb, checked in by Raymond Wagner <rwagner@…>, 13 years ago

Missed line in 0a770b5ea

  • Property mode set to 100755
File size: 4.2 KB
Line 
1#!/usr/bin/env python
2# -*- coding: UTF-8 -*-
3#----------------------------
4# Name: logrotate.py
5# Python Script
6# Author: Raymond Wagner
7# Purpose
8#   This python script is intended to help manage the new logging format
9#   introduced to MythTV in version 0.25. Each instance of each application
10#   run generates a new log file, meaning log rotation applications do not
11#   know to treat them as a group.
12#   This script treats each application individually, and will delete
13#   anything beyond a minimum number of log sets that have aged beyond the
14#   minimum number of days.  One log set is one instance of the application,
15#   and however many rotated files have been generated for it.
16#----------------------------
17
18import os
19import re
20import sys
21from datetime import datetime, timedelta
22from optparse import OptionParser
23
24class LogFile( object ):
25    path = None
26    application = None
27    datetime = None
28    pid = None
29    compressed = False
30    sequence = None
31
32    @classmethod
33    def filter(cls, path, filelist):
34        r = re.compile("[a-z]*.[0-9]{14}.[0-9]{1,6}.log(.[0-9]+(.[a-zA-Z0-9]+)?)?")
35        return [cls(path, f) for f in filelist if r.match(f)]
36
37    def __init__(self, path, filename):
38        self.path = path
39        self.filename = filename
40        self.lastmod = datetime.fromtimestamp(os.stat(
41                            os.path.join(self.path, self.filename)).st_mtime)
42
43        s = filename.split('.')
44        self.application = s[0]
45        self.datetime = datetime.strptime(s[1], "%Y%m%d%H%M%S")
46        self.pid = int(s[2])
47        if len(s) > 4:
48            self.sequence = int(s[4])
49            if len(s) > 5:
50                self.compressed = True
51        self.children = []
52
53    def __repr__(self):
54        return "<LogFile %s, %s%s%s>" % \
55                (self.application, self.datetime.strftime("%b %d, %H:%M"),
56                 " #%d" % self.sequence if self.sequence is not None else "",
57                 " (compressed)" if self.compressed else "")
58
59    def __cmp__(self, other):
60        if self.application != other.application:
61            return cmp(self.application, other.application)
62
63        if self.datetime != other.datetime:
64            return cmp(self.datetime, other.datetime)
65
66        if self.pid != other.pid:
67            return cmp(self.pid, other.pid)
68
69        if self.sequence != other.sequence:
70            if self.sequence is None:
71                return -1
72            if other.sequence is None:
73                return 1
74            return cmp(self.sequence, other.sequence)
75
76        return 0
77
78    def append(self, child):
79        self.children.append(child)
80
81    def delete(self):
82        for child in self.children:
83            child.delete()
84        #print 'deleting %s' % os.path.join(self.path, self.filename)
85        os.unlink(os.path.join(self.path, self.filename))
86
87def deletelogs(instances, opts):
88    while len(instances) > int(opts.minfiles):
89        if instances[0].lastmod > (datetime.now() -\
90                                   timedelta(hours=24*int(opts.minage))):
91            return
92        instances.pop(0).delete()
93
94def main(opts):
95    ls = sorted(LogFile.filter(opts.logpath, os.listdir(opts.logpath)))
96    if len(ls) == 0:
97        print "Warning: Empty log path!"
98        sys.exit(1)
99
100    cur = None
101    while len(ls):
102        f = ls.pop(0)
103        if cur is None:
104            instances = [f]
105            cur = f
106            continue
107
108        if cur.application != f.application:
109            ls.insert(0,f)
110            cur = None
111            deletelogs(instances, opts)
112            continue
113
114        if (cur.datetime != f.datetime) and (cur.pid != f.pid):
115            cur = f
116            instances.append(f)
117            continue
118
119        cur.append(f)
120
121    deletelogs(instances, opts)
122
123if __name__ == "__main__":
124    parser = OptionParser()
125    parser.add_option("-p", "--path", dest="logpath", default="/var/log/mythtv",
126                      help="Path where log files are stored")
127    parser.add_option("-n", "--min-files", dest="minfiles", default="5",
128                      help="Minimum number of logs per application to keep")
129    parser.add_option("-t", "--min-age", dest="minage", default="7",
130                      help="Minimum time (days) to keep log files")
131
132    (opts, args) = parser.parse_args()
133    main(opts)
Note: See TracBrowser for help on using the repository browser.