fail sooner on user and group error. Fix issue #75.

Note: the process could be extended to other variable that need specific
parsing.
This commit is contained in:
benoitc 2010-12-12 12:38:47 +01:00
parent c4312b94c9
commit b62055d529
6 changed files with 59 additions and 25 deletions

View File

@ -33,7 +33,15 @@ class Application(object):
self.cfg = None self.cfg = None
self.callable = None self.callable = None
self.logger = None self.logger = None
self.load_config() self.do_load_config()
def do_load_config(self):
try:
self.load_config()
except Exception, e:
sys.stderr.write("\nError: %s\n" % str(e))
sys.stderr.flush()
sys.exit(1)
def load_config(self): def load_config(self):
# init configuration # init configuration
@ -91,7 +99,7 @@ class Application(object):
raise NotImplementedError raise NotImplementedError
def reload(self): def reload(self):
self.load_config() self.do_load_config()
if self.cfg.spew: if self.cfg.spew:
debug.spew() debug.spew()
loglevel = self.LOG_LEVELS.get(self.cfg.loglevel.lower(), logging.INFO) loglevel = self.LOG_LEVELS.get(self.cfg.loglevel.lower(), logging.INFO)

View File

@ -97,7 +97,7 @@ class DjangoApplicationCommand(Application):
self.options = options self.options = options
self.admin_media_path = admin_media_path self.admin_media_path = admin_media_path
self.callable = None self.callable = None
self.load_config() self.do_load_config()
def load_config(self): def load_config(self):
self.cfg = Config() self.cfg = Config()
@ -124,7 +124,7 @@ class DjangoApplicationCommand(Application):
try: try:
self.cfg.set(k.lower(), v) self.cfg.set(k.lower(), v)
except: except:
sys.stderr.write("Invalid value for %s: %s\n\n" % (k, v)) sys.stderr.write("Invalid value for %s: %s [%s]\n\n" % (k, v))
raise raise
for k, v in list(self.options.items()): for k, v in list(self.options.items()):

View File

@ -114,9 +114,14 @@ class PasterServerApplication(PasterBaseApplication):
cfg[k] = v cfg[k] = v
cfg["default_proc_name"] = cfg['__file__'] cfg["default_proc_name"] = cfg['__file__']
for k, v in list(cfg.items()): try:
if k.lower() in self.cfg.settings and v is not None: for k, v in list(cfg.items()):
self.cfg.set(k.lower(), v) if k.lower() in self.cfg.settings and v is not None:
self.cfg.set(k.lower(), v)
except Exception, e:
sys.stderr.write("\nConfig error: %s\n" % str(e))
sys.stderr.flush()
sys.exit(1)
self.configure_logging() self.configure_logging()

View File

@ -14,7 +14,7 @@ import sys
import time import time
import traceback import traceback
from gunicorn.errors import HaltServer from gunicorn.errors import ConfigError, HaltServer
from gunicorn.pidfile import Pidfile from gunicorn.pidfile import Pidfile
from gunicorn.sock import create_socket from gunicorn.sock import create_socket
from gunicorn import util from gunicorn import util
@ -146,6 +146,7 @@ class Arbiter(object):
"Main master loop." "Main master loop."
self.start() self.start()
util._setproctitle("master [%s]" % self.proc_name) util._setproctitle("master [%s]" % self.proc_name)
self.manage_workers() self.manage_workers()
while True: while True:
try: try:

View File

@ -9,10 +9,12 @@ import inspect
import optparse import optparse
import os import os
import pwd import pwd
import sys
import textwrap import textwrap
import types import types
from gunicorn import __version__ from gunicorn import __version__
from gunicorn.errors import ConfigError
from gunicorn import util from gunicorn import util
KNOWN_SETTINGS = [] KNOWN_SETTINGS = []
@ -87,23 +89,11 @@ class Config(object):
@property @property
def uid(self): def uid(self):
user = self.settings['user'].get() return self.settings['user'].get()
if not user:
return os.geteuid()
elif user.isdigit() or isinstance(user, int):
return int(user)
else:
return pwd.getpwnam(user).pw_uid
@property @property
def gid(self): def gid(self):
group = self.settings['group'].get() return self.settings['group'].get()
if not group:
return os.getegid()
elif group.isdigit() or isinstance(group, int):
return int(group)
else:
return grp.getgrnam(group).gr_gid
@property @property
def proc_name(self): def proc_name(self):
@ -217,6 +207,28 @@ def validate_callable(arity):
return _validate_callable return _validate_callable
def validate_user(val):
if val is None:
return os.geteuid()
elif val.isdigit() or isinstance(val, int):
return int(val)
else:
try:
return pwd.getpwnam(val).pw_uid
except KeyError:
raise ConfigError("No such user: '%s'" % val)
def validate_group(val):
if val is None:
return os.getegid()
elif val.isdigit() or isinstance(val, int):
return int(val)
else:
try:
return grp.getgrnam(val).gr_gid
except KeyError:
raise ConfigError("No such group: '%s'" % val)
class ConfigFile(Setting): class ConfigFile(Setting):
name = "config" name = "config"
section = "Config File" section = "Config File"
@ -446,7 +458,7 @@ class User(Setting):
section = "Server Mechanics" section = "Server Mechanics"
cli = ["-u", "--user"] cli = ["-u", "--user"]
meta = "USER" meta = "USER"
validator = validate_string validator = validate_user
default = None default = None
desc = """\ desc = """\
Switch worker processes to run as this user. Switch worker processes to run as this user.
@ -461,7 +473,7 @@ class Group(Setting):
section = "Server Mechanics" section = "Server Mechanics"
cli = ["-g", "--group"] cli = ["-g", "--group"]
meta = "GROUP" meta = "GROUP"
validator = validate_string validator = validate_group
default = None default = None
desc = """\ desc = """\
Switch worker process to run as this group. Switch worker process to run as this group.

View File

@ -1,3 +1,8 @@
# -*- coding: utf-8 -
#
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.
class HaltServer(Exception): class HaltServer(Exception):
def __init__(self, reason, exit_status=1): def __init__(self, reason, exit_status=1):
@ -6,3 +11,6 @@ class HaltServer(Exception):
def __str__(self): def __str__(self):
return "<HaltServer %r %d>" % (self.reason, self.exit_status) return "<HaltServer %r %d>" % (self.reason, self.exit_status)
class ConfigError(Exception):
""" Exception raised on config error """