Package logilab-common-0 ::
Package 36 ::
Package 1 ::
Module daemon
|
|
1 """A daemon mix-in class.
2
3 :copyright: 2000-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
4 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
5 :license: General Public License version 2 - http://www.gnu.org/licenses
6 """
7 __docformat__ = "restructuredtext en"
8
9 import os, signal, sys, time
10 from logilab.common.logger import make_logger, LOG_ALERT, LOG_NOTICE
11
13 """Mixin to make a daemon from watchers/queriers.
14 """
15
17 self.delay = configmod.DELAY
18 self.name = str(self.__class__).split('.')[-1]
19 self._pid_file = os.path.join('/tmp', '%s.pid'%self.name)
20 if os.path.exists(self._pid_file):
21 raise Exception('''Another instance of %s must be running.
22 If it i not the case, remove the file %s''' % (self.name, self._pid_file))
23 self._alive = 1
24 self._sleeping = 0
25 treshold = configmod.LOG_TRESHOLD
26 if configmod.NODETACH:
27 configmod.log = make_logger('print', treshold, self.name).log
28 else:
29 configmod.log = make_logger('syslog', treshold, self.name).log
30 self.config = configmod
31
33 if not self.config.NODETACH:
34
35 if (os.fork()):
36 return -1
37
38 os.setsid()
39
40
41
42 if (os.fork()):
43 return -1
44
45 os.chdir('/')
46
47 os.umask(077)
48
49 f = open(self._pid_file, 'w')
50 f.write(str(os.getpid()))
51 f.close()
52
53 sys.stdin.close()
54 sys.stdout.close()
55 sys.stderr.close()
56
57 signal.signal(signal.SIGTERM, self.signal_handler)
58 signal.signal(signal.SIGHUP, self.signal_handler)
59
60
62 """ optionaly go in daemon mode and
63 do what concrete classe has to do and pauses for delay between runs
64 If self.delay is negative, do a pause before starting
65 """
66 if self._daemonize() == -1:
67 return
68 self.config.log(LOG_NOTICE, '%s instance started' % self.name)
69 if self.delay < 0:
70 self.delay = -self.delay
71 time.sleep(self.delay)
72 while 1:
73 try:
74 self._run()
75 except Exception, e:
76
77
78 self.config.log(LOG_ALERT, 'Internal error: %s'%(e))
79 if not self._alive:
80 break
81 try:
82 self._sleeping = 1
83 time.sleep(self.delay)
84 self._sleeping = 0
85 except SystemExit:
86 break
87 self.config.log(LOG_NOTICE, '%s instance exited'%self.name)
88
89 os.remove(self._pid_file)
90
92 if sig_num == signal.SIGTERM:
93 if self._sleeping:
94
95 self.config.log(LOG_NOTICE, 'exit on SIGTERM')
96 sys.exit(0)
97 else:
98 self.config.log(LOG_NOTICE, 'exit on SIGTERM (on next turn)')
99 self._alive = 0
100 elif sig_num == signal.SIGHUP:
101 self.config.log(LOG_NOTICE, 'reloading configuration on SIGHUP')
102 reload(self.config)
103
105 """should be overidden in the mixed class"""
106 raise NotImplementedError()
107
108
109
110 L_OPTIONS = ["help", "log=", "delay=", 'no-detach']
111 S_OPTIONS = 'hl:d:n'
112
114 print """ --help or -h
115 displays this message
116 --log <log_level>
117 log treshold (7 record everything, 0 record only emergency.)
118 Defaults to %s
119 --delay <delay>
120 the number of seconds between two runs.
121 Defaults to %s""" % (modconfig.LOG_TRESHOLD, modconfig.DELAY)
122
124 if opt_name in ('-h','--help'):
125 help_meth()
126 sys.exit(0)
127 elif opt_name in ('-l','--log'):
128 modconfig.LOG_TRESHOLD = int(opt_value)
129 elif opt_name in ('-d', '--delay'):
130 modconfig.DELAY = int(opt_value)
131 elif opt_name in ('-n', '--no-detach'):
132 modconfig.NODETACH = 1
133