Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Side by Side Diff: third_party/twisted_8_1/twisted/scripts/_twistd_unix.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.test.test_twistd -*-
2 # Copyright (c) 2001-2008 Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5 import warnings
6 import os, errno, sys
7
8 from twisted.python import log, syslog, logfile
9 from twisted.python.util import switchUID, uidFromString, gidFromString
10 from twisted.application import app, service
11 from twisted import copyright
12
13
14 class ServerOptions(app.ServerOptions):
15 synopsis = "Usage: twistd [options]"
16
17 optFlags = [['nodaemon','n', "don't daemonize"],
18 ['quiet', 'q', "No-op for backwards compatibility."],
19 ['originalname', None, "Don't try to change the process name"],
20 ['syslog', None, "Log to syslog, not to file"],
21 ['euid', '',
22 "Set only effective user-id rather than real user-id. "
23 "(This option has no effect unless the server is running as "
24 "root, in which case it means not to shed all privileges "
25 "after binding ports, retaining the option to regain "
26 "privileges in cases such as spawning processes. "
27 "Use with caution.)"],
28 ]
29
30 optParameters = [
31 ['prefix', None,'twisted',
32 "use the given prefix when syslogging"],
33 ['pidfile','','twistd.pid',
34 "Name of the pidfile"],
35 ['chroot', None, None,
36 'Chroot to a supplied directory before running'],
37 ['uid', 'u', None, "The uid to run as.", uidFromString],
38 ['gid', 'g', None, "The gid to run as.", gidFromString],
39 ]
40 zsh_altArgDescr = {"prefix":"Use the given prefix when syslogging (default: twisted)",
41 "pidfile":"Name of the pidfile (default: twistd.pid)",}
42 #zsh_multiUse = ["foo", "bar"]
43 #zsh_mutuallyExclusive = [("foo", "bar"), ("bar", "baz")]
44 zsh_actions = {"pidfile":'_files -g "*.pid"', "chroot":'_dirs'}
45 zsh_actionDescr = {"chroot":"chroot directory"}
46
47 def opt_version(self):
48 """Print version information and exit.
49 """
50 print 'twistd (the Twisted daemon) %s' % copyright.version
51 print copyright.copyright
52 sys.exit()
53
54
55 def postOptions(self):
56 app.ServerOptions.postOptions(self)
57 if self['pidfile']:
58 self['pidfile'] = os.path.abspath(self['pidfile'])
59
60
61 def checkPID(pidfile):
62 if not pidfile:
63 return
64 if os.path.exists(pidfile):
65 try:
66 pid = int(open(pidfile).read())
67 except ValueError:
68 sys.exit('Pidfile %s contains non-numeric value' % pidfile)
69 try:
70 os.kill(pid, 0)
71 except OSError, why:
72 if why[0] == errno.ESRCH:
73 # The pid doesnt exists.
74 log.msg('Removing stale pidfile %s' % pidfile, isError=True)
75 os.remove(pidfile)
76 else:
77 sys.exit("Can't check status of PID %s from pidfile %s: %s" %
78 (pid, pidfile, why[1]))
79 else:
80 sys.exit("""\
81 Another twistd server is running, PID %s\n
82 This could either be a previously started instance of your application or a
83 different application entirely. To start a new one, either run it in some other
84 directory, or use the --pidfile and --logfile parameters to avoid clashes.
85 """ % pid)
86
87 def _getLogObserver(logfilename, sysLog, prefix, nodaemon):
88 """
89 Create and return a suitable log observer for the given configuration.
90
91 The observer will go to syslog using the prefix C{prefix} if C{sysLog} is
92 true. Otherwise, it will go to the file named C{logfilename} or, if
93 C{nodaemon} is true and C{logfilename} is C{"-"}, to stdout.
94
95 @type logfilename: C{str}
96 @param logfilename: The name of the file to which to log, if other than the
97 default.
98
99 @type sysLog: C{bool}
100 @param sysLog: A flag indicating whether to use syslog instead of file
101 logging.
102
103 @type prefix: C{str}
104 @param prefix: If C{sysLog} is C{True}, the string prefix to use for syslog
105 messages.
106
107 @type nodaemon: C{bool}
108 @param nodaemon: A flag indicating the process will not be daemonizing.
109
110 @return: An object suitable to be passed to C{log.addObserver}.
111 """
112 if sysLog:
113 observer = syslog.SyslogObserver(prefix).emit
114 else:
115 if logfilename == '-':
116 if not nodaemon:
117 print 'daemons cannot log to stdout'
118 os._exit(1)
119 logFile = sys.stdout
120 elif nodaemon and not logfilename:
121 logFile = sys.stdout
122 else:
123 logFile = logfile.LogFile.fromFullPath(logfilename or 'twistd.log')
124 try:
125 import signal
126 except ImportError:
127 pass
128 else:
129 def rotateLog(signal, frame):
130 from twisted.internet import reactor
131 reactor.callFromThread(logFile.rotate)
132 signal.signal(signal.SIGUSR1, rotateLog)
133 observer = log.FileLogObserver(logFile).emit
134 return observer
135
136
137 def startLogging(*args, **kw):
138 warnings.warn(
139 """
140 Use ApplicationRunner instead of startLogging.
141 """,
142 category=PendingDeprecationWarning,
143 stacklevel=2)
144 observer = _getLogObserver(*args, **kw)
145 log.startLoggingWithObserver(observer)
146 sys.stdout.flush()
147
148
149 def daemonize():
150 # See http://www.erlenstar.demon.co.uk/unix/faq_toc.html#TOC16
151 if os.fork(): # launch child and...
152 os._exit(0) # kill off parent
153 os.setsid()
154 if os.fork(): # launch child and...
155 os._exit(0) # kill off parent again.
156 os.umask(077)
157 null = os.open('/dev/null', os.O_RDWR)
158 for i in range(3):
159 try:
160 os.dup2(null, i)
161 except OSError, e:
162 if e.errno != errno.EBADF:
163 raise
164 os.close(null)
165
166
167 def launchWithName(name):
168 if name and name != sys.argv[0]:
169 exe = os.path.realpath(sys.executable)
170 log.msg('Changing process name to ' + name)
171 os.execv(exe, [name, sys.argv[0], '--originalname'] + sys.argv[1:])
172
173
174 class UnixApplicationRunner(app.ApplicationRunner):
175 """
176 An ApplicationRunner which does Unix-specific things, like fork,
177 shed privileges, and maintain a PID file.
178 """
179
180 def preApplication(self):
181 """
182 Do pre-application-creation setup.
183 """
184 checkPID(self.config['pidfile'])
185 self.config['nodaemon'] = (self.config['nodaemon']
186 or self.config['debug'])
187 self.oldstdout = sys.stdout
188 self.oldstderr = sys.stderr
189
190
191 def getLogObserver(self):
192 """
193 Override to supply a log observer suitable for POSIX based on the given
194 arguments.
195 """
196 return _getLogObserver(
197 self.config['logfile'], self.config['syslog'],
198 self.config['prefix'], self.config['nodaemon'])
199
200
201 def postApplication(self):
202 """
203 To be called after the application is created: start the
204 application and run the reactor. After the reactor stops,
205 clean up PID files and such.
206 """
207 self.startApplication(self.application)
208 self.startReactor(None, self.oldstdout, self.oldstderr)
209 self.removePID(self.config['pidfile'])
210 log.msg("Server Shut Down.")
211
212
213 def removePID(self, pidfile):
214 """
215 Remove the specified PID file, if possible. Errors are logged, not
216 raised.
217
218 @type pidfile: C{str}
219 @param pidfile: The path to the PID tracking file.
220 """
221 if not pidfile:
222 return
223 try:
224 os.unlink(pidfile)
225 except OSError, e:
226 if e.errno == errno.EACCES or e.errno == errno.EPERM:
227 log.msg("Warning: No permission to delete pid file")
228 else:
229 log.msg("Failed to unlink PID file:")
230 log.deferr()
231 except:
232 log.msg("Failed to unlink PID file:")
233 log.deferr()
234
235
236 def setupEnvironment(self, chroot, rundir, nodaemon, pidfile):
237 """
238 Set the filesystem root, the working directory, and daemonize.
239
240 @type chroot: C{str} or L{NoneType}
241 @param chroot: If not None, a path to use as the filesystem root (using
242 L{os.chroot}).
243
244 @type rundir: C{str}
245 @param rundir: The path to set as the working directory.
246
247 @type nodaemon: C{bool}
248 @param nodaemon: A flag which, if set, indicates that daemonization
249 should not be done.
250
251 @type pidfile: C{str} or C{NoneType}
252 @param pidfile: If not C{None}, the path to a file into which to put
253 the PID of this process.
254 """
255 if chroot is not None:
256 os.chroot(chroot)
257 if rundir == '.':
258 rundir = '/'
259 os.chdir(rundir)
260 if not nodaemon:
261 daemonize()
262 if pidfile:
263 open(pidfile,'wb').write(str(os.getpid()))
264
265
266 def shedPrivileges(self, euid, uid, gid):
267 """
268 Change the UID and GID or the EUID and EGID of this process.
269
270 @type euid: C{bool}
271 @param euid: A flag which, if set, indicates that only the I{effective}
272 UID and GID should be set.
273
274 @type uid: C{int} or C{NoneType}
275 @param uid: If not C{None}, the UID to which to switch.
276
277 @type gid: C{int} or C{NoneType}
278 @param gid: If not C{None}, the GID to which to switch.
279 """
280 if uid is not None or gid is not None:
281 switchUID(uid, gid, euid)
282 extra = euid and 'e' or ''
283 log.msg('set %suid/%sgid %s/%s' % (extra, extra, uid, gid))
284
285
286 def startApplication(self, application):
287 """
288 Configure global process state based on the given application and run
289 the application.
290
291 @param application: An object which can be adapted to
292 L{service.IProcess} and L{service.IService}.
293 """
294 process = service.IProcess(application)
295 if not self.config['originalname']:
296 launchWithName(process.processName)
297 self.setupEnvironment(
298 self.config['chroot'], self.config['rundir'],
299 self.config['nodaemon'], self.config['pidfile'])
300
301 service.IService(application).privilegedStartService()
302
303 uid, gid = self.config['uid'], self.config['gid']
304 if uid is None:
305 uid = process.uid
306 if gid is None:
307 gid = process.gid
308
309 self.shedPrivileges(self.config['euid'], uid, gid)
310 app.startApplication(application, not self.config['no_save'])
311
312
313
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/scripts/__init__.py ('k') | third_party/twisted_8_1/twisted/scripts/_twistw.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698