From 5afec8d7268b081ba2f1a806b08bd2418519aa59 Mon Sep 17 00:00:00 2001 From: benoitc Date: Mon, 22 Feb 2010 16:29:35 +0100 Subject: [PATCH] add setproctitle support. -n allow to customize the name. by default it's the arg passed to command line for wsgi app, module.settings for djang and ini file path for paster --- gunicorn/arbiter.py | 11 ++++++++--- gunicorn/config.py | 1 + gunicorn/main.py | 16 +++++++++++++++- gunicorn/management/commands/run_gunicorn.py | 11 +++++++++-- gunicorn/util.py | 8 ++++++++ 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index 8b5477ae..bc7cdfb1 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -7,6 +7,7 @@ from __future__ import with_statement import copy import errno +import inspect import logging import os import select @@ -43,10 +44,11 @@ class Arbiter(object): if name[:3] == "SIG" and name[3] != "_" ) - def __init__(self, address, num_workers, modname, **kwargs): + def __init__(self, address, num_workers, app, **kwargs): self.address = address self.num_workers = num_workers - self.modname = modname + self.app = app + self.timeout = 30 self.reexec_pid = 0 self.debug = kwargs.get("debug", False) @@ -55,6 +57,7 @@ class Arbiter(object): self.conf = kwargs.get("config", {}) self._pidfile = None self.master_name = "Master" + self.app_name = self.conf['app_name'] # get current path, try to use PWD env first try: @@ -160,6 +163,7 @@ class Arbiter(object): def run(self): """ main master loop. Launch to start the master""" self.start() + util._setproctitle("master [%s]" % self.app_name) self.manage_workers() while True: try: @@ -355,7 +359,7 @@ class Arbiter(object): if i in workers: continue - worker = Worker(i, self.pid, self.LISTENER, self.modname, + worker = Worker(i, self.pid, self.LISTENER, self.app, self.timeout/2.0, self.conf) self.conf.before_fork(self, worker) pid = os.fork() @@ -366,6 +370,7 @@ class Arbiter(object): # Process Child worker_pid = os.getpid() try: + util._setproctitle("worker [%s]" % self.app_name) self.log.debug("Worker %s booting" % worker_pid) self.conf.after_fork(self, worker) worker.run() diff --git a/gunicorn/config.py b/gunicorn/config.py index 287b756b..d56d0952 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -13,6 +13,7 @@ from gunicorn import util class Config(object): DEFAULTS = dict( + app_name = os.getcwd(), bind='127.0.0.1:8000', daemon=False, debug=False, diff --git a/gunicorn/main.py b/gunicorn/main.py index 63ac3fc2..93316987 100644 --- a/gunicorn/main.py +++ b/gunicorn/main.py @@ -42,6 +42,8 @@ def options(): help="Change worker user"), op.make_option('-g', '--group', dest="group", help="Change worker group"), + op.make_option('-n', '--name', dest='app_name', + help="Application name"), op.make_option('--log-level', dest='loglevel', help='Log level below which to silence messages. [info]'), op.make_option('--log-file', dest='logfile', @@ -141,6 +143,8 @@ def paste_server(app, global_conf=None, host="127.0.0.1", port=None, if key == "debug": value = (value == "true") options[key] = value + if not 'app_name' in options: + options['app_name'] = options['__file__'] conf = Config(options) arbiter = Arbiter(conf.address, conf.workers, app, debug=conf["debug"], @@ -162,6 +166,9 @@ def run(): if len(args) != 1: parser.error("No application module specified.") + if not opts.app_name: + opts.app_name = args[0] + try: return util.import_app(args[0]) except: @@ -202,7 +209,11 @@ def run_django(): # set environ settings_name, ext = os.path.splitext(os.path.basename(settings_path)) - os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name) + settings_modname = '%s.%s' % (project_name, settings_name) + os.environ['DJANGO_SETTINGS_MODULE'] = settings_modname + + if not opts.app_name: + opts.app_name = settings_modname # django wsgi app return django.core.handlers.wsgi.WSGIHandler() @@ -259,6 +270,9 @@ def run_paster(): if not opts.debug: opts.debug = (ctx.global_conf.get('debug') == "true") + + if not opts.app_name: + opts.app_name = ctx.global_conf.get('__file__') app = loadapp(config_url, relative_to=relative_to) return app diff --git a/gunicorn/management/commands/run_gunicorn.py b/gunicorn/management/commands/run_gunicorn.py index 2209a4a5..c30cfd73 100644 --- a/gunicorn/management/commands/run_gunicorn.py +++ b/gunicorn/management/commands/run_gunicorn.py @@ -17,7 +17,7 @@ from django.core.handlers.wsgi import WSGIHandler from gunicorn.arbiter import Arbiter from gunicorn.config import Config -from gunicorn.main import daemonize, UMASK, set_owner_process, configure_logging +from gunicorn.main import daemonize, UMASK, configure_logging from gunicorn.util import parse_address, to_bytestring class Command(BaseCommand): @@ -36,6 +36,8 @@ class Command(BaseCommand): help="Change worker user"), make_option('-g', '--group', dest="group", help="Change worker group"), + make_option('-n', '--name', dest='app_name', + help="Application name"), ) help = "Starts a fully-functional Web server using gunicorn." args = '[optional port number, or ipaddr:port or unix:/path/to/sockfile]' @@ -48,6 +50,9 @@ class Command(BaseCommand): raise CommandError('Usage is runserver %s' % self.args) options['bind'] = addrport or '127.0.0.1' + + if not options.get('app_name'): + options['app_name'] =settings.SETTINGS_MODULE conf = Config(options) admin_media_path = options.get('admin_media_path', '') @@ -55,13 +60,15 @@ class Command(BaseCommand): print "Validating models..." self.validate(display_num_errors=True) - print "\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE) + print "\nDjango version %s, using settings %r" % (django.get_version(), + settings.SETTINGS_MODULE) print "Development server is running at %s" % str(conf.address) print "Quit the server with %s." % quit_command # django.core.management.base forces the locale to en-us. translation.activate(settings.LANGUAGE_CODE) + try: handler = AdminMediaHandler(WSGIHandler(), admin_media_path) arbiter = Arbiter(conf.address, conf.workers, handler, diff --git a/gunicorn/util.py b/gunicorn/util.py index 48d4ffa6..fb0e284b 100644 --- a/gunicorn/util.py +++ b/gunicorn/util.py @@ -30,6 +30,14 @@ monthname = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] +try: + from setproctitle import setproctitle + def _setproctitle(title): + setproctitle("gunicorn: %s" % title) +except ImportError: + def _setproctitle(title): + return + def set_owner_process(uid,gid): """ set user and group of workers processes """ if gid: