<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://performiq.com/kb/index.php?action=history&amp;feed=atom&amp;title=Tail.py</id>
	<title>Tail.py - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://performiq.com/kb/index.php?action=history&amp;feed=atom&amp;title=Tail.py"/>
	<link rel="alternate" type="text/html" href="https://performiq.com/kb/index.php?title=Tail.py&amp;action=history"/>
	<updated>2026-05-20T20:48:09Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>https://performiq.com/kb/index.php?title=Tail.py&amp;diff=3098&amp;oldid=prev</id>
		<title>PeterHarding at 06:09, 19 July 2009</title>
		<link rel="alternate" type="text/html" href="https://performiq.com/kb/index.php?title=Tail.py&amp;diff=3098&amp;oldid=prev"/>
		<updated>2009-07-19T06:09:06Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 16:09, 19 July 2009&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l129&quot;&gt;Line 129:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 129:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Python]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Python]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Tools]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Tools]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[Category:Examples]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>PeterHarding</name></author>
	</entry>
	<entry>
		<id>https://performiq.com/kb/index.php?title=Tail.py&amp;diff=2225&amp;oldid=prev</id>
		<title>PeterHarding: New page: =Script=  &lt;pre&gt; #!/usr/bin/python  &#039;&#039;&#039;A module which implements a unix-like &quot;tail&quot; of a file. A callback is made for every new line found in the file.  Options specify whether the existing...</title>
		<link rel="alternate" type="text/html" href="https://performiq.com/kb/index.php?title=Tail.py&amp;diff=2225&amp;oldid=prev"/>
		<updated>2008-05-27T04:19:29Z</updated>

		<summary type="html">&lt;p&gt;New page: =Script=  &amp;lt;pre&amp;gt; #!/usr/bin/python  &amp;#039;&amp;#039;&amp;#039;A module which implements a unix-like &amp;quot;tail&amp;quot; of a file. A callback is made for every new line found in the file.  Options specify whether the existing...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;=Script=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;A module which implements a unix-like &amp;quot;tail&amp;quot; of a file.&lt;br /&gt;
A callback is made for every new line found in the file.  Options&lt;br /&gt;
specify whether the existing contents of the file should be read&lt;br /&gt;
or ignored.&lt;br /&gt;
&lt;br /&gt;
@author Sean Reifschneider &amp;lt;jafo@tummy.com&amp;gt;&lt;br /&gt;
@version $Revision: 1.51 $&lt;br /&gt;
&lt;br /&gt;
If a file is emptied or removed, the tail will continue reading lines&lt;br /&gt;
which are written in the new place.&lt;br /&gt;
&lt;br /&gt;
Simple example:&lt;br /&gt;
&lt;br /&gt;
	import tail&lt;br /&gt;
&lt;br /&gt;
	def callback(line):&lt;br /&gt;
		print &amp;#039;Line: &amp;quot;%s&amp;quot;&amp;#039; % string.rstrip(line)&lt;br /&gt;
&lt;br /&gt;
	tail.tail(&amp;#039;/var/log/all&amp;#039;, callback).mainloop()&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
import time&lt;br /&gt;
import string&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
class tail:&lt;br /&gt;
	def __init__(self, filename, callback, tailbytes = 0):&lt;br /&gt;
		&amp;#039;&amp;#039;&amp;#039;Create a new tail instance.&lt;br /&gt;
		Create a tail object which periodicly polls the specified file looking&lt;br /&gt;
		for new data which was written.  The callback routine is called for each&lt;br /&gt;
		new line found in the file.&lt;br /&gt;
&lt;br /&gt;
		@return Nothing&lt;br /&gt;
		@param filename File to read.&lt;br /&gt;
		@param callback Function which takes one argument, called with each&lt;br /&gt;
				line read from the file.&lt;br /&gt;
		@param tailbytes Specifies bytes from end of file to start reading&lt;br /&gt;
				(defaults to 0, meaning skip entire file, -1 means read full file).&lt;br /&gt;
		&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
		self.skip = tailbytes&lt;br /&gt;
		self.filename = filename&lt;br /&gt;
		self.callback = callback&lt;br /&gt;
		self.fp = None&lt;br /&gt;
		self.lastSize = 0&lt;br /&gt;
		self.lastInode = -1&lt;br /&gt;
		self.data = &amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
	def process(self):&lt;br /&gt;
		&amp;#039;&amp;#039;&amp;#039;Examine file looking for new lines.&lt;br /&gt;
		When called, this function will process all lines in the file being&lt;br /&gt;
		tailed, detect the original file being renamed or reopened, etc...&lt;br /&gt;
		This should be called periodicly to look for activity on the file.&lt;br /&gt;
&lt;br /&gt;
		@return Nothing&lt;br /&gt;
		&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
		#  open file if it&amp;#039;s not already open&lt;br /&gt;
		if not self.fp:&lt;br /&gt;
			try:&lt;br /&gt;
				self.fp = open(self.filename, &amp;#039;r&amp;#039;)&lt;br /&gt;
				stat = os.stat(self.filename)&lt;br /&gt;
				self.lastIno = stat[1]&lt;br /&gt;
				if self.skip &amp;gt;= 0 and stat[6] &amp;gt; self.skip:&lt;br /&gt;
					self.fp.seek(0 - (self.skip), 2)&lt;br /&gt;
				self.skip = -1&lt;br /&gt;
				self.lastSize = 0&lt;br /&gt;
			except:&lt;br /&gt;
				if self.fp: self.fp.close()&lt;br /&gt;
				self.skip = -1    #  if the file doesn&amp;#039;t exist, we don&amp;#039;t skip&lt;br /&gt;
				self.fp = None&lt;br /&gt;
		if not self.fp: return&lt;br /&gt;
&lt;br /&gt;
		#  check to see if file has moved under us&lt;br /&gt;
		try:&lt;br /&gt;
			stat = os.stat(self.filename)&lt;br /&gt;
			thisSize = stat[6]&lt;br /&gt;
			thisIno = stat[1]&lt;br /&gt;
			if thisSize &amp;lt; self.lastSize or thisIno != self.lastIno:&lt;br /&gt;
				raise Exception&lt;br /&gt;
		except:&lt;br /&gt;
			self.fp.close()&lt;br /&gt;
			self.fp = None&lt;br /&gt;
			self.data = &amp;#039;&amp;#039;&lt;br /&gt;
			return&lt;br /&gt;
&lt;br /&gt;
		#  read if size has changed&lt;br /&gt;
		if self.lastSize &amp;lt; thisSize:&lt;br /&gt;
			while 1:&lt;br /&gt;
				thisData = self.fp.read(4096)&lt;br /&gt;
				if len(thisData) &amp;lt; 1:&lt;br /&gt;
					break&lt;br /&gt;
				self.data = self.data + thisData&lt;br /&gt;
&lt;br /&gt;
				#  process lines within the data&lt;br /&gt;
				while 1:&lt;br /&gt;
					pos = string.find(self.data, &amp;#039;\n&amp;#039;)&lt;br /&gt;
					if pos &amp;lt; 0: break&lt;br /&gt;
					line = self.data[:pos]&lt;br /&gt;
					self.data = self.data[pos + 1:]&lt;br /&gt;
					#  line is line read from file&lt;br /&gt;
					if self.callback: self.callback(line)&lt;br /&gt;
&lt;br /&gt;
		self.lastSize = thisSize&lt;br /&gt;
		self.lastIno = thisIno&lt;br /&gt;
&lt;br /&gt;
	def mainloop(self, sleepfor = 5):&lt;br /&gt;
		&amp;#039;&amp;#039;&amp;#039;Loop forever processing activity on the tail object.&lt;br /&gt;
		This routine is intended to be called in programs which do not need&lt;br /&gt;
		to do other processing.  This routine never returns.&lt;br /&gt;
&lt;br /&gt;
		@return Never returns&lt;br /&gt;
		@param sleepfor Seconds between processing (default is 5 seconds).&lt;br /&gt;
		&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
		while 1:&lt;br /&gt;
			self.process()&lt;br /&gt;
			time.sleep(sleepfor)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
	def callback(line):&lt;br /&gt;
		print &amp;#039;Line: &amp;quot;%s&amp;quot;&amp;#039; % string.rstrip(line)&lt;br /&gt;
&lt;br /&gt;
	tail(&amp;#039;/var/log/all&amp;#039;, callback).mainloop()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Python]]&lt;br /&gt;
[[Category:Tools]]&lt;/div&gt;</summary>
		<author><name>PeterHarding</name></author>
	</entry>
</feed>