#!/usr/bin/env python
"""
usage: logtail [-d pathname][-n]
-d pathname Use pathname instead of /var/lib/postgresql/8.2/main/pg_log
-n Just print the current log file name and exit
-l List the log file names
-p [files] Run the files through pager
"""
import os, time, sys, getopt, signal
class LogTail:
"""Logfile tailer for rotated log files.
Initially purpouse was to keep tail on PostgreSQL logs, but can be used
with any application that satisfies these assumptions:
* All log files reside in the same directory.
* We can find last log file by sorting the file list alphabetically.
* When log is switched, we start tailing from the last file - assume that
there will be no gaps (sufficiently large files).
"""
def __init__(self,logpath):
"""Initialize the logtailer, open the initial log file."""
self.logpath = logpath
self.logfile = None
self.logf = None
self.probesleft = 2
self.first = True
def getfilenames(self):
"""Return the sorted list of log file names"""
files = []
for f in os.listdir(self.logpath):
if f.startswith("postgresql-20"):
files.append(os.path.join(self.logpath, f))
files.sort()
return files
def getlogname(self):
"""Return the name of current logfile."""
files = self.getfilenames()
if files:
return files[-1]
return None
def readline(self):
"""Read single line from logfile, switch to next file if current
file is exhausted."""
while True:
# If not already open, keep trying until it becomes available
while not self.logf:
self.logfile = self.getlogname()
if not self.logfile:
# initial log file not found
time.sleep(1)
continue
try:
self.logf = open(self.logfile)
self.probesleft = 2
except IOError, msg:
time.sleep(1)
if self.first:
# seek to EOF of first file
self.first = False
self.logf.seek(0, 2)
line = self.logf.readline()
if line:
return line
self.logf.seek(0, 1) # reset EOF condition for next attempt
if self.logfile != self.getlogname():
self.probesleft -= 1
if not self.probesleft:
self.logf = None
else:
time.sleep(0.2)
def __iter__(self):
"""Initialize iterator"""
return self
def next(self):
"""Iterator wrapper for readline()"""
return self.readline()
def view_file(logpath, args):
"""Run the specified files through pager"""
lt = LogTail(logpath)
if not args:
args = [ lt.getlogname() ]
logfiles = lt.getfilenames()
for f in args:
if not f in logfiles or not os.path.exists(f):
print f, "is not a postgres log file."
sys.exit(1)
signal.signal(signal.SIGINT, signal.SIG_IGN)
os.environ["LESSSECURE"] = "1"
os.spawnv(os.P_WAIT, "/usr/bin/less", [ "less", "-n" ] + args)
def usage():
print __doc__
sys.exit(1)
def main():
logpath = "/var/lib/postgresql/8.2/main/pg_log"
try:
opts, args = getopt.getopt(sys.argv[1:], "nlpd:h")
except getopt.error, msg:
print msg
usage()
for opt,arg in opts:
if opt == "-n":
# list current file
print LogTail(logpath).getlogname()
sys.exit(0)
elif opt == "-l":
# list the log files
for f in LogTail(logpath).getfilenames():
print f
sys.exit(0)
elif opt == "-p":
# run the file through pager
view_file(logpath, args)
sys.exit(0)
elif opt == "-d":
logpath = arg;
elif opt == "-h":
usage()
try:
for line in LogTail(logpath):
sys.stdout.write(line)
sys.stdout.flush()
except KeyboardInterrupt:
pass
if __name__ == "__main__":
main()
On Mon, Nov 10, 2008 at 8:46 PM, Greg Smith <gsmith@xxxxxxxxxxxxx> wrote:
Let's say you're using logging_collector and you've put some %-escapes into log_filename for daily log rotation. Perhaps it's daily rotation with this pattern:
log_filename = 'postgresql-%Y-%m-%d.log'
Is there any good way to ask the server what log file name it's currently writing to? I was trying to write something that does a "tail" on the current log, and was hoping there was a simple way to figure out which file that goes against. Looking for the latest timestamp or running strftime would both work I guess, those just seemed a little heavy (was hoping for an "alias"-sized answer) to figure out something that the server certainly knows.
--
* Greg Smith gsmith@xxxxxxxxxxxxx http://www.gregsmith.com Baltimore, MD
--
Sent via pgsql-general mailing list (pgsql-general@xxxxxxxxxxxxxx)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general