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.
|
# This file is part of gunicorn released under the MIT license.
|
||||||
# See the NOTICE for more information.
|
# See the NOTICE for more information.
|
||||||
|
|
||||||
|
from __future__ import with_statement
|
||||||
|
|
||||||
import errno
|
import errno
|
||||||
import fcntl
|
import fcntl
|
||||||
import logging
|
import logging
|
||||||
@ -11,12 +13,14 @@ import select
|
|||||||
import signal
|
import signal
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from gunicorn.worker import Worker
|
from gunicorn.worker import Worker
|
||||||
|
|
||||||
class Arbiter(object):
|
class Arbiter(object):
|
||||||
|
|
||||||
|
|
||||||
LISTENER = None
|
LISTENER = None
|
||||||
WORKERS = {}
|
WORKERS = {}
|
||||||
PIPE = []
|
PIPE = []
|
||||||
@ -32,19 +36,78 @@ class Arbiter(object):
|
|||||||
if name[:3] == "SIG" and name[3] != "_"
|
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.address = address
|
||||||
self.num_workers = num_workers
|
self.num_workers = num_workers
|
||||||
self.modname = modname
|
self.modname = modname
|
||||||
self.timeout = 30
|
self.timeout = 30
|
||||||
self.reexec_pid = 0
|
self.reexec_pid = 0
|
||||||
self.pid = os.getpid()
|
self.pid = os.getpid()
|
||||||
self.debug = debug
|
self.debug = kwargs.get("debug", False)
|
||||||
self.log = logging.getLogger(__name__)
|
self.log = logging.getLogger(__name__)
|
||||||
self.init_signals()
|
self.init_signals()
|
||||||
self.listen(self.address)
|
self.listen(self.address)
|
||||||
|
self.pidfile = kwargs.get("pidfile")
|
||||||
self.log.info("Booted Arbiter: %s" % os.getpid())
|
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):
|
def init_signals(self):
|
||||||
if self.PIPE:
|
if self.PIPE:
|
||||||
@ -150,8 +213,10 @@ class Arbiter(object):
|
|||||||
self.stop(False)
|
self.stop(False)
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
self.log.info("Master is shutting down.")
|
|
||||||
self.stop()
|
self.stop()
|
||||||
|
self.log.info("Master is shutting down.")
|
||||||
|
if self.pidfile:
|
||||||
|
self.unlink_pidfile(self.pidfile)
|
||||||
|
|
||||||
def handle_chld(self, sig, frame):
|
def handle_chld(self, sig, frame):
|
||||||
self.wakeup()
|
self.wakeup()
|
||||||
|
|||||||
@ -25,6 +25,8 @@ def options():
|
|||||||
help='Port to listen on. [%default]'),
|
help='Port to listen on. [%default]'),
|
||||||
op.make_option('--workers', dest='workers', type='int',
|
op.make_option('--workers', dest='workers', type='int',
|
||||||
help='Number of workers to spawn. [%default]'),
|
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',
|
op.make_option('--log-level', dest='loglevel', default='info',
|
||||||
help='Log level below which to silence messages. [%default]'),
|
help='Log level below which to silence messages. [%default]'),
|
||||||
op.make_option('--log-file', dest='logfile', default='-',
|
op.make_option('--log-file', dest='logfile', default='-',
|
||||||
@ -66,9 +68,14 @@ def main(usage, get_app):
|
|||||||
port = int(port)
|
port = int(port)
|
||||||
else:
|
else:
|
||||||
port = 8000
|
port = 8000
|
||||||
|
|
||||||
|
kwargs = dict(
|
||||||
|
debug=opts.debug,
|
||||||
|
pidfile=opts.pidfile
|
||||||
|
)
|
||||||
|
|
||||||
arbiter = Arbiter((host,port), workers, app,
|
arbiter = Arbiter((host,port), workers, app,
|
||||||
opts.debug)
|
**kwargs)
|
||||||
arbiter.run()
|
arbiter.run()
|
||||||
|
|
||||||
def paste_server(app, global_conf=None, host="127.0.0.1", port=None,
|
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:
|
if debug:
|
||||||
# we force to one worker in debug mode.
|
# we force to one worker in debug mode.
|
||||||
workers = 1
|
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,
|
arbiter = Arbiter(bind_addr, workers, app, **kwargs)
|
||||||
debug)
|
|
||||||
arbiter.run()
|
arbiter.run()
|
||||||
Loading…
x
Reference in New Issue
Block a user