/usr/share/pyshared/circuits/app/daemon.py is in python-circuits 2.1.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 132 133 134 135 136 137 | # Module: daemon
# Date: 20th June 2009
# Author: James Mills, prologic at shortcircuit dot net dot au
"""Daemon Component
Component to daemonizae a system into the background and detach it from its
controlling PTY. Supports PID file writing, logging stdin, stdout and stderr
and changing the current working directory.
"""
import os
import sys
import errno
from circuits.core import handler, BaseComponent, Event
class Daemonize(Event):
"""Daemonize Event
This event can be fired to notify the `Daemon` Component to begin the
"daemonization" process. This event is (*by default*) used
automatically by the `Daemon` Component in its "started" Event
Handler (*This behavior can be overridden*).
Arguments: *None*
"""
class WritePID(Event):
""""WritePID Event
This event can be fired to notify the `Daemon` Component that is should
retrive the current process's id (pid) and write it out to the
configured path in the `Daemon` Component. This event (*by default*)
is used automatically by the `Daemon` Component after the
:class:`Daemonize`.
"""
class Daemon(BaseComponent):
"""Daemon Component
:param pidfile: .pid filename
:type pidfile: str or unicode
:param stdin: filename to log stdin
:type stdin: str or unicode
:param stdout: filename to log stdout
:type stdout: str or unicode
:param stderr: filename to log stderr
:type stderr: str or unicode
"""
channel = "daemon"
def __init__(self, pidfile, path="/", stdin=None, stdout=None,
stderr=None, channel=channel):
"x.__init__(...) initializes x; see x.__class__.__doc__ for signature"
super(Daemon, self).__init__(channel=channel)
assert os.path.isabs(path), "path must be absolute"
if os.path.isabs(pidfile):
self._pidfile = pidfile
else:
self._pidfile = os.path.join(path, pidfile)
self._path = path
stdio_attrs = ["_stdin", "_stdout", "_stderr"]
for i, stdio in enumerate([stdin, stdout, stderr]):
if stdio and os.path.isabs(stdio):
setattr(self, stdio_attrs[i], stdio)
elif stdio:
setattr(self, stdio_attrs[i], os.path.join(path, stdio))
else:
setattr(self, stdio_attrs[i], "/dev/null")
@handler("write_pid")
def _on_writepid(self):
f = open(self._pidfile, "w")
f.write(str(os.getpid()))
f.close()
@handler("daemonize")
def _on_daemonize(self):
# Do first fork.
try:
pid = os.fork()
if pid > 0:
# Exit first parent
os._exit(0)
except OSError as e:
print >> sys.stderr, "fork #1 failed: (%d) %s\n" % (errno, str(e))
raise SystemExit(1)
# Decouple from parent environment.
os.chdir(self._path)
os.umask(0o077)
os.setsid()
# Do second fork.
try:
pid = os.fork()
if pid > 0:
# Exit second parent
os._exit(0)
except OSError as e:
print >> sys.stderr, "fork #2 failed: (%d) %s\n" % (e, str(e))
raise SystemExit(1)
# Now I am a daemon!
# Redirect standard file descriptors.
si = open(self._stdin, "r")
so = open(self._stdout, "a+")
se = open(self._stderr, "a+")
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
self.fire(WritePID())
@handler("started", filter=True, priority=100.0, channel="*")
def _on_started(self, component):
if component is not self:
self.fire(Daemonize())
@handler("registered")
def _on_registered(self, component, manager):
if component == self and manager.root.running:
self.fire(Daemonize())
|