====== Fifologger package ======
===== What is it? =====
The ''fifologger'' is a simple package you can use to log messages to a FIFO under a *nix operating system. It's a basically a simple convenience class that takes the messy parts of connecting to the "write end" of a FIFO and logging to it. This is quite handy if you want to connect and see what is happening with output from your script at different times, particularly with something you've daemonized, but you don't want to deal with logging to an actual file and you don't really care about losing messages.
===== The Script =====
#!/usr/bin/env python
# $Id: fifologger.py 86 2008-12-18 20:10:39Z jay $
import os , time , stat
__all__ = ['FifoError' , 'FifoLog']
"""
You can use the FifoLog class to log messages to a fifo.
Usage is simple:
import fifologger
fifo = '/var/tmp/test.fifo'
l = fifologger.FifoLog(fifo)
for i in xrange(1000):
l.log('hello world #%d' % i)
time.sleep(1)
l.close()
Then, just simply run:
$ cat /var/tmp/test.fifo
And you should see the "hello world" messages printed to your term.
"""
class FifoError(Exception):
pass
class FifoLog():
"""
This class is set up to make it easy to log to a FIFO under a *nix
based operating system. This allows you to simply connect
to the read end of the pipe whenever you want to hop on a
log stream, but you don't have the overhead of rotating log
files and reattaching to new logs, etc.
Note that if there is not a process connected to the read end
of the pipe, all messages sent to this logger will be
dropped until a reader connects.
"""
def __init__(self , fifoPath , showTime=True):
self._fifoPath = fifoPath
self._fd = -1
self._showTime = showTime
def log(self , msg):
"""
Logs the message to the fifo. Returns True if a reader was
connected and it was successfully logged, False otherwise.
"""
if self._fd < 0:
# We don't have an open handle, attempt to open the fifo
try:
self._openFifo()
except FifoError:
# FifoErrors are bad, send those all the way up
raise
except Exception , err:
# A simple connection error just means there is no attached
# reader, just reset the file descriptor and return False
self._fd = -1
return False
if self._showTime:
# Add a time.ctime() to the beginning of the msg
msg = '%s: %s' % (time.ctime() , msg)
msg = msg.strip()
retries = 0
while retries < 3:
# Try to write to the fifo 3 times, then fail
try:
os.write(self._fd , '%s\n' % msg)
except Exception , err:
retries += 1
else:
return True
return False
def close():
"""
Closes down the write end of the pipe, if it is open
"""
if self._fd > 0:
os.close(self._fd)
def isFifo(self , path):
"""
Returns a bool indicating whether the given path is a fifo
"""
s = os.stat(path)
if s[0] & stat.S_IFIFO:
return True
return False
def _openFifo(self):
"""
Attempts to open the fifo
"""
if os.path.exists(self._fifoPath) and \
not self.isFifo(self._fifoPath):
# We have a file with the same name as the fifo path, but
# it is not a fifo, raise an exception
raise FifoError , 'The file, %s, is not a fifo' % self._fifoPath
elif not os.path.exists(self._fifoPath):
# Nothing exists at the path so create the fifo
os.mkfifo(self._fifoPath)
# Attempt to open the write end of the pipe
self._fd = os.open(self._fifoPath , os.O_WRONLY | os.O_NONBLOCK)
if __name__ == '__main__':
# Run a test
fifo = '/var/tmp/test.fifo'
l = FifoLog(fifo)
for i in xrange(1000):
l.log('hello world #%d' % i)
time.sleep(1)
l.close()
===== Usage =====
import fifologger
fifo = '/var/tmp/test.fifo'
l = fifologger.FifoLog(fifo)
for i in xrange(1000):
l.log('hello world #%d' % i)
time.sleep(1)
l.close()
===== Install =====
Simply {{:programming:python:fifologger.py.gz|download the script}} or copy the above into a file and put the file in your ''lib/python/site-packages'' directory. This is usually something to the effect of ''/usr/lib/python2.4/site-packages'' but it varies depending on the distro.