-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathundead.py
131 lines (110 loc) · 4.06 KB
/
undead.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
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Undead
===========
Dead Easy UNIX Daemons!
"""
class Undead(object):
""" This is the Undead module """
def __init__(self, name=None, log_level='WARNING',
log_handler=None, proc_title = None, **kwargs):
self.settings = {
'chroot_directory': None,
'working_directory': u'/',
'umask': 0,
'uid': None,
'gid': None,
'prevent_core': True,
'detach_process': None,
'files_preserve': None,
'pidfile': None,
'stdin': None,
'stdout': None,
'stderr': None,
'signal_map': None,
}
self.settings.update(kwargs)
self.name = name
self.log_level = log_level
self.log_handler = log_handler
def __getattr__(self, name):
if name in self.settings:
return self.settings[name]
else:
raise AttributeError
self.__getattr__ = __getattr__
def __setattr__(self, name, value):
if name in self.settings:
self.settings[name] = value
else:
self.__dict__[name] = value
self.__setattr__ = __setattr__
@property
def working_dir(self):
import warnings
warnings.warn("Deprecated, please use working_directory instead.",
DeprecationWarning, stacklevel=2)
return self.settings['working_directory']
@working_dir.setter
def working(self, value):
self.settings['working_directory'] = value
@property
def pid(self):
return self.settings['pidfile']
@pid.setter
def pid(self, value):
import warnings
warnings.warn("Deprecated, please use pidfile instead.",
DeprecationWarning, stacklevel=2)
self.settings['pidfile'] = value
def __call__(self, action, *args, **kwargs):
""" Alias for start """
return self.start(action)
def start(self, action):
import os
import inspect
import daemon
import lockfile
import logbook
from setproctitle import setproctitle
self.name = self.name or action.__name__
default_dir = os.path.join(os.path.expanduser("~"),
".{0}".format(self.name))
if self.settings['pidfile'] is None:
self.settings['pidfile'] = os.path.join(default_dir, "{0}.pid".format(self.name))
if not os.path.exists(default_dir):
os.makedirs(default_dir)
if isinstance(self.settings['pidfile'], basestring):
pid = str(os.getpid())
with open(self.settings['pidfile'], 'w') as pidfile:
pidfile.write(pid)
self.settings['pidfile'] = lockfile.FileLock(self.settings['pidfile'])
if isinstance(self.proc_title, basestring):
setproctitle(self.proc_title)
# Initialize logging if requested.
action_args = inspect.getargspec(action)[0]
if 'log' in action_args:
self.log = logbook.Logger(self.name)
if self.log_handler is None:
if not os.path.exists(default_dir):
os.makedirs(default_dir)
self.log_handler = logbook.FileHandler(
os.path.join(default_dir, "{0}.log".format(self.name)))
if self.settings['files_preserve'] is None:
self.settings['files_preserve'] = [self.log_handler.stream]
else:
self.settings['files_preserve'].append(self.log_handler.stream)
self.log_handler.level_name = self.log_level
with self.log_handler.applicationbound():
self.log.warning("Starting daemon.")
with daemon.DaemonContext(**self.settings):
action(log=self.log)
else:
with daemon.DaemonContext(**self.settings):
action()
undead = Undead()
import sys
sys.modules[__name__] = undead
# Removing from module ns
del sys