I use the following code to track ssh log-ins:
def follow(thefile):
thefile.seek(0,2)
while True:
line = thefile.readline()
if not line:
time.sleep(0.1)
continue
yield line
if __name__ == '__main__':
logfile = open('/var/log/auth.log', 'r')
loglines = follow(logfile)
for line in loglines:
print 'do something here'
I've noticed that this script suddenly stops working after a couple of days. I don't get any error, it doesn't terminate, it just stops working, as if readline()
would never return.
So I executed a echo 'test' >> auth.log.1
and this indeed ends up getting processed by the script, because sometime ago auth.log
got renamed to auth.log.1
How can I track when such a log rotation happens and adjust accordingly?
To verify if a particular log is indeed rotating or not and to check the last date and time of its rotation, check the /var/lib/logrotate/status file. This is a neatly formatted file that contains the log file name and the date on which it was last rotated.
The logrotate program is a log file manager. It is used to regularly cycle (or rotate) log files by removing the oldest ones from your system and creating new log files. It may be used to rotate based on the age of the file or the file's size, and usually runs automatically through the cron utility.
The main logrotate configuration file is located at /etc/logrotate. conf . The file contains the default parameters that logrotate uses when it rotates logs. The file is commented, so you can skim it to see how the configuration is set up.
Using e4c5's answer I ended up with this code, which also solves the issue of calling readline()
multiple times per second.
During the first invocation it skips to the end of the file and waits for modifications. When the file is moved, it reopens the file and reads the entire content, then starts to wait.
import os
import time
import traceback
import threading
import inotify.adapters
logfile = b'/var/log/auth.log'
#logfile = b'logfile.log'
##################################################################
def process(line, history=False):
if history:
print '=', line.strip('\n')
else:
print '>', line.strip('\n')
##################################################################
from_beginning = False
notifier = inotify.adapters.Inotify()
while True:
try:
#------------------------- check
if not os.path.exists(logfile):
print 'logfile does not exist'
time.sleep(1)
continue
print 'opening and starting to watch', logfile
#------------------------- open
file = open(logfile, 'r')
if from_beginning:
for line in file.readlines():
process(line, history=True)
else:
file.seek(0,2)
from_beginning = True
#------------------------- watch
notifier.add_watch(logfile)
try:
for event in notifier.event_gen():
if event is not None:
(header, type_names, watch_path, filename) = event
if set(type_names) & set(['IN_MOVE_SELF']): # moved
print 'logfile moved'
notifier.remove_watch(logfile)
file.close()
time.sleep(1)
break
elif set(type_names) & set(['IN_MODIFY']): # modified
for line in file.readlines():
process(line, history=False)
except (KeyboardInterrupt, SystemExit):
raise
except:
notifier.remove_watch(logfile)
file.close()
time.sleep(1)
#-------------------------
except (KeyboardInterrupt, SystemExit):
break
except inotify.calls.InotifyError:
time.sleep(1)
except IOError:
time.sleep(1)
except:
traceback.print_exc()
time.sleep(1)
##################################################################
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With