mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
add pidfile support. gunicorn --pid=/tmp/gunicorn.pid or paster server
prod.ini pid=/tmp/gunicorn.pid
This commit is contained in:
parent
ddb48593f3
commit
d5880e2bcf
@ -3,6 +3,8 @@
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
from __future__ import with_statement
|
||||
|
||||
import errno
|
||||
import fcntl
|
||||
import logging
|
||||
@ -11,12 +13,14 @@ import select
|
||||
import signal
|
||||
import socket
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
from gunicorn.worker import Worker
|
||||
|
||||
class Arbiter(object):
|
||||
|
||||
|
||||
LISTENER = None
|
||||
WORKERS = {}
|
||||
PIPE = []
|
||||
@ -32,19 +36,78 @@ class Arbiter(object):
|
||||
if name[:3] == "SIG" and name[3] != "_"
|
||||
)
|
||||
|
||||
def __init__(self, address, num_workers, modname, debug=False):
|
||||
_pidfile = None
|
||||
|
||||
def __init__(self, address, num_workers, modname,
|
||||
**kwargs):
|
||||
self.address = address
|
||||
self.num_workers = num_workers
|
||||
self.modname = modname
|
||||
self.timeout = 30
|
||||
self.reexec_pid = 0
|
||||
self.pid = os.getpid()
|
||||
self.debug = debug
|
||||
self.debug = kwargs.get("debug", False)
|
||||
self.log = logging.getLogger(__name__)
|
||||
self.init_signals()
|
||||
self.listen(self.address)
|
||||
self.pidfile = kwargs.get("pidfile")
|
||||
self.log.info("Booted Arbiter: %s" % os.getpid())
|
||||
|
||||
|
||||
def _del_pidfile(self):
|
||||
self._pidfile = None
|
||||
|
||||
def _get_pidfile(self):
|
||||
return self._pidfile
|
||||
|
||||
def _set_pidfile(self, path):
|
||||
if not path:
|
||||
return
|
||||
|
||||
pid = self.valid_pidfile(path)
|
||||
if pid:
|
||||
if self.pidfile and path == self.pidfile and pid == os.getpid():
|
||||
return path
|
||||
raise RuntimeError("Already running on PID %s " \
|
||||
"(or pid file '%s' is stale)" % (os.getpid(), path))
|
||||
if self.pidfile:
|
||||
self.unlink_pidfile(self.pidfile)
|
||||
|
||||
# write pidfile
|
||||
fd, fname = tempfile.mkstemp()
|
||||
os.write(fd, "%s\n" % self.pid)
|
||||
os.rename(fname, path)
|
||||
os.close(fd)
|
||||
self._pidfile = path
|
||||
pidfile = property(_get_pidfile, _set_pidfile, _del_pidfile)
|
||||
|
||||
|
||||
def unlink_pidfile(self, path):
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
if int(f.read() or 0) == self.pid:
|
||||
os.unlink(f)
|
||||
except:
|
||||
pass
|
||||
|
||||
def valid_pidfile(self, path):
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
pid = int(f.read() or 0)
|
||||
if pid <= 0: return
|
||||
|
||||
try:
|
||||
os.kill(pid, 0)
|
||||
return pid
|
||||
except OSError, e:
|
||||
if e[0] == errno.ESRCH:
|
||||
return
|
||||
raise
|
||||
except IOError, e:
|
||||
if e[0] == errno.ENOENT:
|
||||
return
|
||||
raise
|
||||
|
||||
|
||||
def init_signals(self):
|
||||
if self.PIPE:
|
||||
@ -150,8 +213,10 @@ class Arbiter(object):
|
||||
self.stop(False)
|
||||
sys.exit(-1)
|
||||
|
||||
self.log.info("Master is shutting down.")
|
||||
self.stop()
|
||||
self.log.info("Master is shutting down.")
|
||||
if self.pidfile:
|
||||
self.unlink_pidfile(self.pidfile)
|
||||
|
||||
def handle_chld(self, sig, frame):
|
||||
self.wakeup()
|
||||
|
||||
@ -25,6 +25,8 @@ def options():
|
||||
help='Port to listen on. [%default]'),
|
||||
op.make_option('--workers', dest='workers', type='int',
|
||||
help='Number of workers to spawn. [%default]'),
|
||||
op.make_option('-p','--pid', dest='pidfile',
|
||||
help='set the background PID FILE'),
|
||||
op.make_option('--log-level', dest='loglevel', default='info',
|
||||
help='Log level below which to silence messages. [%default]'),
|
||||
op.make_option('--log-file', dest='logfile', default='-',
|
||||
@ -66,9 +68,14 @@ def main(usage, get_app):
|
||||
port = int(port)
|
||||
else:
|
||||
port = 8000
|
||||
|
||||
kwargs = dict(
|
||||
debug=opts.debug,
|
||||
pidfile=opts.pidfile
|
||||
)
|
||||
|
||||
arbiter = Arbiter((host,port), workers, app,
|
||||
opts.debug)
|
||||
**kwargs)
|
||||
arbiter.run()
|
||||
|
||||
def paste_server(app, global_conf=None, host="127.0.0.1", port=None,
|
||||
@ -88,7 +95,15 @@ def paste_server(app, global_conf=None, host="127.0.0.1", port=None,
|
||||
if debug:
|
||||
# we force to one worker in debug mode.
|
||||
workers = 1
|
||||
|
||||
pid = kwargs.get("pid")
|
||||
if global_conf:
|
||||
pid = global_conf.get('pid', pid)
|
||||
|
||||
kwargs = dict(
|
||||
debug=debug,
|
||||
pidfile=pid
|
||||
)
|
||||
|
||||
arbiter = Arbiter(bind_addr, workers, app,
|
||||
debug)
|
||||
arbiter = Arbiter(bind_addr, workers, app, **kwargs)
|
||||
arbiter.run()
|
||||
Loading…
x
Reference in New Issue
Block a user