Subversion Repositories SmartDukaan

Rev

Rev 20125 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3894 chandransh 1
#!/usr/bin/env python
2
 
3
'''
4
This daemon has been taken from the blog post of 
5
<a href="http://www.jejik.com/authors/sander_marechal/">Sander Marechal</a>
6
at http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/
7
 
8
Some of the references within the code comments are no longer available.
9
 
10
'''
11
 
12
import sys, os, time, atexit
19283 amit.gupta 13
from signal import SIGTERM
14
import logging 
3894 chandransh 15
 
16
class Daemon:
17
	"""
18
	A generic daemon class.
19
 
20
	Usage: subclass the Daemon class and override the run() method
21
	"""
22
	def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
23
		self.stdin = stdin
24
		self.stdout = stdout
25
		self.stderr = stderr
26
		self.pidfile = pidfile
20125 amit.gupta 27
		if stdout!='/dev/null':
20130 amit.gupta 28
			configure_logging()
3894 chandransh 29
 
30
	def daemonize(self):
31
		"""
32
		do the UNIX double-fork magic, see Stevens' "Advanced 
33
		Programming in the UNIX Environment" for details (ISBN 0201563177)
34
		http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
35
		"""
36
		try: 
37
			pid = os.fork() 
38
			if pid > 0:
39
				# exit first parent
40
				sys.exit(0) 
41
		except OSError, e: 
42
			sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
43
			sys.exit(1)
44
 
45
		# decouple from parent environment
46
		os.chdir("/") 
47
		os.setsid() 
48
		os.umask(0) 
49
 
50
		# do second fork
51
		try: 
52
			pid = os.fork() 
53
			if pid > 0:
54
				# exit from second parent
55
				sys.exit(0) 
56
		except OSError, e: 
57
			sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
58
			sys.exit(1) 
59
 
60
		# redirect standard file descriptors
61
		sys.stdout.flush()
62
		sys.stderr.flush()
63
		si = file(self.stdin, 'r')
19284 amit.gupta 64
		so = file(self.stdout, 'a+')
65
		se = file(self.stderr, 'a+', 0)
3894 chandransh 66
		os.dup2(si.fileno(), sys.stdin.fileno())
67
		os.dup2(so.fileno(), sys.stdout.fileno())
68
		os.dup2(se.fileno(), sys.stderr.fileno())
69
 
70
		# write pidfile
71
		atexit.register(self.delpid)
72
		pid = str(os.getpid())
73
		file(self.pidfile,'w+').write("%s\n" % pid)
74
 
75
	def delpid(self):
76
		os.remove(self.pidfile)
77
 
78
	def start(self):
79
		"""
80
		Start the daemon
81
		"""
82
		# Check for a pidfile to see if the daemon already runs
83
		try:
84
			pf = file(self.pidfile,'r')
85
			pid = int(pf.read().strip())
86
			pf.close()
87
		except IOError:
88
			pid = None
89
 
90
		if pid:
91
			message = "pidfile %s already exist. Daemon already running?\n"
92
			sys.stderr.write(message % self.pidfile)
93
			sys.exit(1)
94
 
95
		# Start the daemon
96
		self.daemonize()
97
		self.run()
98
 
99
	def stop(self):
100
		"""
101
		Stop the daemon
102
		"""
103
		# Get the pid from the pidfile
104
		try:
105
			pf = file(self.pidfile,'r')
106
			pid = int(pf.read().strip())
107
			pf.close()
108
		except IOError:
109
			pid = None
110
 
111
		if not pid:
112
			message = "pidfile %s does not exist. Daemon not running?\n"
113
			sys.stderr.write(message % self.pidfile)
114
			return # not an error in a restart
115
 
116
		# Try killing the daemon process	
117
		try:
118
			while 1:
119
				os.kill(pid, SIGTERM)
120
				time.sleep(0.1)
121
		except OSError, err:
122
			err = str(err)
123
			if err.find("No such process") > 0:
124
				if os.path.exists(self.pidfile):
125
					os.remove(self.pidfile)
126
			else:
127
				print str(err)
128
				sys.exit(1)
129
 
130
	def restart(self):
131
		"""
132
		Restart the daemon
133
		"""
134
		self.stop()
135
		self.start()
136
 
137
	def run(self):
138
		"""
139
		You should override this method when you subclass Daemon. It will be called after the process has been
140
		daemonized by start() or restart().
141
		"""
142
		pass
19766 amit.gupta 143
 
20130 amit.gupta 144
def configure_logging():
145
	thriftLogger = logging.getLogger("thrift")
146
	ch = logging.StreamHandler(sys.stdout)
147
	thriftLogger.setLevel(logging.ERROR)
148
	thriftLogger.addHandler(ch)