-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpyUnixDaemon.py
119 lines (114 loc) · 3.69 KB
/
pyUnixDaemon.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/python
# AVERTISSEMENTS:
# Cette classe ne peut en aucun cas etre utilise a des fins lucratives
# (sauf autorisation ecrite).
# Je me degage de toute responsabilite quant aux consequences liees a
# l'utilisation du contenu de ce fichier.
# Tous droits reserves - Steve MULLER 2007
import signal
import os
import sys
class pyUnixDaemon:
""" This class implements a UNIX daemon. You can derived from it to build
your own daemon.
"""
def __init__(self, lockFilename = "/var/run/pyUnixDaemon.pid", user = (0, 0)):
""" This method initializes some internal variables and instancies an
object.
"""
self._user = user
self._lockFilename = lockFilename
def _daemonExists(self):
""" This method checks if the lock file exists.
"""
return os.path.exists(self._lockFilename)
def _lock(self):
""" This method creates the lock file and write the daemon pid.
"""
self._lockFile = open(self._lockFilename, "w")
self._lockFile.write("%d" % (os.getpid()))
self._lockFile.flush()
def _unlock(self):
""" This method closes and removes the lock file.
"""
self._lockFile.close()
os.unlink(self._lockFilename)
def _fork(self):
""" This method forks the daemon using the unix way.
"""
if (self._daemonExists()):
print "[Error] Could not be daemonized: already in memory"
sys.exit(1)
try:
pid = os.fork()
if (pid > 0):
sys.exit(0)
except OSError, e:
print "[Error] Fork #1 failed: %s (%d)" % (e.strerror, e.errno)
sys.exit(1)
os.chdir("/")
os.setsid()
os.umask(0)
try:
pid = os.fork()
if (pid > 0):
sys.exit(0)
except OSError, e:
print "[Error] Fork #2 failed: %s (%d)" % (e.strerror, e.errno)
sys.exit(1)
def _run(self):
""" This method must be derivated to do something.
"""
while(self._loop):
pass
def __signalHandler(self, signalNumber, frame):
""" This method sets an internal flag that permits to break the forever
loop.
"""
self._loop = False
def setOutput(self, output, error = None):
""" This method redirects stdout and stderr flows.
"""
self._stdout = sys.stdout
self._output = output
self._stderr = sys.stderr
if (error is not None):
self._error = error
else:
self._error = output
def launch(self):
""" This method prepares all required actions before lauching the background method '_run'.
"""
self._fork()
self._lock()
os.setegid(self._user[1])
os.seteuid(self._user[0])
self._loop = True
signal.signal(signal.SIGTERM, self.__signalHandler)
sys.stdout = self._output
sys.stderr = self._error
self._run()
sys.stdout = self._stdout
sys.stderr = self._stderr
os.setegid(0)
os.seteuid(0)
self._unlock()
"""
EXEMPLE
if (__name__ == "__main__"):
from datetime import datetime
from os import getpid
from time import sleep
import sys
class pyTest(pyUnixDaemon):
def __init__(self, lockFilename):
pyUnixDaemon.__init__(self, lockFilename)
def _run(self):
while(self._loop):
print "%s - %s" % (datetime.now(), getpid())
sys.stdout.flush()
sleep(5)
daemon = pyTest("/var/run/pyTest.pid")
daemon.setOutput(open("/var/log/pyTest.log", "a"))
daemon.launch()
"""