Subversion Repositories SmartDukaan

Rev

Rev 19283 | Go to most recent revision | Details | 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
13
from signal import SIGTERM 
14
 
15
class Daemon:
16
	"""
17
	A generic daemon class.
18
 
19
	Usage: subclass the Daemon class and override the run() method
20
	"""
21
	def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
22
		self.stdin = stdin
23
		self.stdout = stdout
24
		self.stderr = stderr
25
		self.pidfile = pidfile
26
 
27
	def daemonize(self):
28
		"""
29
		do the UNIX double-fork magic, see Stevens' "Advanced 
30
		Programming in the UNIX Environment" for details (ISBN 0201563177)
31
		http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
32
		"""
33
		try: 
34
			pid = os.fork() 
35
			if pid > 0:
36
				# exit first parent
37
				sys.exit(0) 
38
		except OSError, e: 
39
			sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
40
			sys.exit(1)
41
 
42
		# decouple from parent environment
43
		os.chdir("/") 
44
		os.setsid() 
45
		os.umask(0) 
46
 
47
		# do second fork
48
		try: 
49
			pid = os.fork() 
50
			if pid > 0:
51
				# exit from second parent
52
				sys.exit(0) 
53
		except OSError, e: 
54
			sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
55
			sys.exit(1) 
56
 
57
		# redirect standard file descriptors
58
		sys.stdout.flush()
59
		sys.stderr.flush()
60
		si = file(self.stdin, 'r')
61
		so = file(self.stdout, 'a+')
62
		se = file(self.stderr, 'a+', 0)
63
		os.dup2(si.fileno(), sys.stdin.fileno())
64
		os.dup2(so.fileno(), sys.stdout.fileno())
65
		os.dup2(se.fileno(), sys.stderr.fileno())
66
 
67
		# write pidfile
68
		atexit.register(self.delpid)
69
		pid = str(os.getpid())
70
		file(self.pidfile,'w+').write("%s\n" % pid)
71
 
72
	def delpid(self):
73
		os.remove(self.pidfile)
74
 
75
	def start(self):
76
		"""
77
		Start the daemon
78
		"""
79
		# Check for a pidfile to see if the daemon already runs
80
		try:
81
			pf = file(self.pidfile,'r')
82
			pid = int(pf.read().strip())
83
			pf.close()
84
		except IOError:
85
			pid = None
86
 
87
		if pid:
88
			message = "pidfile %s already exist. Daemon already running?\n"
89
			sys.stderr.write(message % self.pidfile)
90
			sys.exit(1)
91
 
92
		# Start the daemon
93
		self.daemonize()
94
		self.run()
95
 
96
	def stop(self):
97
		"""
98
		Stop the daemon
99
		"""
100
		# Get the pid from the pidfile
101
		try:
102
			pf = file(self.pidfile,'r')
103
			pid = int(pf.read().strip())
104
			pf.close()
105
		except IOError:
106
			pid = None
107
 
108
		if not pid:
109
			message = "pidfile %s does not exist. Daemon not running?\n"
110
			sys.stderr.write(message % self.pidfile)
111
			return # not an error in a restart
112
 
113
		# Try killing the daemon process	
114
		try:
115
			while 1:
116
				os.kill(pid, SIGTERM)
117
				time.sleep(0.1)
118
		except OSError, err:
119
			err = str(err)
120
			if err.find("No such process") > 0:
121
				if os.path.exists(self.pidfile):
122
					os.remove(self.pidfile)
123
			else:
124
				print str(err)
125
				sys.exit(1)
126
 
127
	def restart(self):
128
		"""
129
		Restart the daemon
130
		"""
131
		self.stop()
132
		self.start()
133
 
134
	def run(self):
135
		"""
136
		You should override this method when you subclass Daemon. It will be called after the process has been
137
		daemonized by start() or restart().
138
		"""
139
		pass