示例#1
0
                print 'Using HTTP/1.1 protocol version'
            httpd.serve_forever()
    elif options.protocol in ('scgi', 'ajp', 'fcgi'):
        def serve():
            server_cls = __import__('flup.server.%s' % options.protocol,
                                    None, None, ['']).WSGIServer
            flup_app = wsgi_app
            if options.unquote:
                from trac.web.fcgi_frontend import FlupMiddleware
                flup_app = FlupMiddleware(flup_app)
            ret = server_cls(flup_app, bindAddress=server_address).run()
            sys.exit(42 if ret else 0) # if SIGHUP exit with status 42

    try:
        if options.daemonize:
            daemon.daemonize(pidfile=options.pidfile, progname='tracd',
                             umask=options.umask)
        if options.group is not None:
            os.setgid(options.group)
        if options.user is not None:
            os.setuid(options.user)

        if options.autoreload:
            def modification_callback(file):
                print >> sys.stderr, 'Detected modification of %s, ' \
                                     'restarting.' % file
            autoreload.main(serve, modification_callback)
        else:
            serve()

    except OSError, e:
        print >> sys.stderr, '%s: %s' % (e.__class__.__name__, e)
示例#2
0
def main():
    from optparse import OptionParser, OptionValueError
    parser = OptionParser(usage='usage: %prog [options] [projenv] ...',
                          version='%%prog %s' % VERSION)

    auths = {}
    def _auth_callback(option, opt_str, value, parser, cls):
        info = value.split(',', 3)
        if len(info) != 3:
            raise OptionValueError("Incorrect number of parameters for %s"
                                   % option)

        env_name, filename, realm = info
        if env_name in auths:
            print >> sys.stderr, 'Ignoring duplicate authentication option ' \
                                 'for project: %s' % env_name
        else:
            auths[env_name] = cls(os.path.abspath(filename), realm)

    def _validate_callback(option, opt_str, value, parser, valid_values):
        if value not in valid_values:
            raise OptionValueError('%s must be one of: %s, not %s'
                                   % (opt_str, '|'.join(valid_values), value))
        setattr(parser.values, option.dest, value)

    def _octal(option, opt_str, value, parser):
        try:
            setattr(parser.values, option.dest, int(value, 8))
        except ValueError:
            raise OptionValueError('Invalid octal umask value: %r' % value)
    
    parser.add_option('-a', '--auth', action='callback', type='string',
                      metavar='DIGESTAUTH', callback=_auth_callback,
                      callback_args=(DigestAuthentication,),
                      help='[projectdir],[htdigest_file],[realm]')
    parser.add_option('--basic-auth', action='callback', type='string',
                      metavar='BASICAUTH', callback=_auth_callback,
                      callback_args=(BasicAuthentication,),
                      help='[projectdir],[htpasswd_file],[realm]')

    parser.add_option('-p', '--port', action='store', type='int', dest='port',
                      help='the port number to bind to')
    parser.add_option('-b', '--hostname', action='store', dest='hostname',
                      help='the host name or IP address to bind to')
    parser.add_option('--protocol', action='callback', type="string",
                      dest='protocol', callback=_validate_callback,
                      callback_args=(('http', 'scgi', 'ajp', 'fcgi'),),
                      help='http|scgi|ajp|fcgi')
    parser.add_option('-q', '--unquote', action='store_true',
                      dest='unquote',
                      help='unquote PATH_INFO (may be needed when using ajp)')
    parser.add_option('--http10', action='store_false', dest='http11',
                      help='use HTTP/1.0 protocol version instead of HTTP/1.1')
    parser.add_option('--http11', action='store_true', dest='http11',
                      help='use HTTP/1.1 protocol version (default)')
    parser.add_option('-e', '--env-parent-dir', action='store',
                      dest='env_parent_dir', metavar='PARENTDIR',
                      help='parent directory of the project environments')
    parser.add_option('--base-path', action='store', type='string', # XXX call this url_base_path?
                      dest='base_path',
                      help='the initial portion of the request URL\'s "path"')

    parser.add_option('-r', '--auto-reload', action='store_true',
                      dest='autoreload',
                      help='restart automatically when sources are modified')

    parser.add_option('-s', '--single-env', action='store_true',
                      dest='single_env', help='only serve a single '
                      'project without the project list', default=False)

    if os.name == 'posix':
        parser.add_option('-d', '--daemonize', action='store_true',
                          dest='daemonize',
                          help='run in the background as a daemon')
        parser.add_option('--pidfile', action='store',
                          dest='pidfile',
                          help='When daemonizing, file to which to write pid')
        parser.add_option('--umask', action='callback', type='string',
                          dest='umask', metavar='MASK', callback=_octal,
                          help='When daemonizing, file mode creation mask '
                          'to use, in octal notation (default 022)')

    parser.set_defaults(port=None, hostname='', base_path='', daemonize=False,
                        protocol='http', http11=True, umask=022)
    options, args = parser.parse_args()

    if not args and not options.env_parent_dir:
        parser.error('either the --env-parent-dir option or at least one '
                     'environment must be specified')
    if options.single_env:
        if options.env_parent_dir:
            parser.error('the --single-env option cannot be used with '
                         '--env-parent-dir')
        elif len(args) > 1:
            parser.error('the --single-env option cannot be used with '
                         'more than one enviroment')
    if options.daemonize and options.autoreload:
        parser.error('the --auto-reload option cannot be used with '
                     '--daemonize')

    if options.port is None:
        options.port = {
            'http': 80,
            'scgi': 4000,
            'ajp': 8009,
            'fcgi': 8000,
        }[options.protocol]
    server_address = (options.hostname, options.port)

    # relative paths don't work when daemonized
    args = [os.path.abspath(a) for a in args]
    if options.env_parent_dir:
        options.env_parent_dir = os.path.abspath(options.env_parent_dir)
    if parser.has_option('pidfile') and options.pidfile:
        options.pidfile = os.path.abspath(options.pidfile)

    wsgi_app = TracEnvironMiddleware(dispatch_request,
                                     options.env_parent_dir, args,
                                     options.single_env)
    if auths:
        if options.single_env:
            project_name = os.path.basename(args[0])
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name)
        else:
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths)
    base_path = options.base_path.strip('/')
    if base_path:
        wsgi_app = BasePathMiddleware(wsgi_app, base_path)

    if options.protocol == 'http':
        def serve():
            httpd = TracHTTPServer(server_address, wsgi_app,
                                   options.env_parent_dir, args,
                                   use_http_11=options.http11)

            print 'Server starting in PID %i.' % os.getpid()
            addr, port = server_address
            if not addr or addr == '0.0.0.0':
                print 'Serving on 0.0.0.0:%s view at http://127.0.0.1:%s/%s' \
                       % (port, port, base_path)
            else:
                print 'Serving on http://%s:%s/%s' % (addr, port, base_path)
            if options.http11:
                print 'Using HTTP/1.1 protocol version'
            httpd.serve_forever()
    elif options.protocol in ('scgi', 'ajp', 'fcgi'):
        def serve():
            server_cls = __import__('flup.server.%s' % options.protocol,
                                    None, None, ['']).WSGIServer
            flup_app = wsgi_app
            if options.unquote:
                from trac.web.fcgi_frontend import FlupMiddleware
                flup_app = FlupMiddleware(flup_app)
            ret = server_cls(flup_app, bindAddress=server_address).run()
            sys.exit(ret and 42 or 0) # if SIGHUP exit with status 42

    try:
        if options.daemonize:
            daemon.daemonize(pidfile=options.pidfile, progname='tracd',
                             umask=options.umask)

        if options.autoreload:
            def modification_callback(file):
                print >> sys.stderr, 'Detected modification of %s, ' \
                                     'restarting.' % file
            autoreload.main(serve, modification_callback)
        else:
            serve()

    except OSError:
        sys.exit(1)
    except KeyboardInterrupt:
        pass
示例#3
0
def main():
    from optparse import OptionParser, OptionValueError
    parser = OptionParser(usage='usage: %prog [options] [projenv] ...',
                          version='%%prog %s' % VERSION)

    auths = {}

    def _auth_callback(option, opt_str, value, parser, cls):
        info = value.split(',', 3)
        if len(info) != 3:
            raise OptionValueError("Incorrect number of parameters for %s" %
                                   option)

        env_name, filename, realm = info
        if env_name in auths:
            print('Ignoring duplicate authentication option for project: %s' %
                  env_name,
                  file=sys.stderr)
        else:
            auths[env_name] = cls(os.path.abspath(filename), realm)

    def _validate_callback(option, opt_str, value, parser, valid_values):
        if value not in valid_values:
            raise OptionValueError('%s must be one of: %s, not %s' %
                                   (opt_str, '|'.join(valid_values), value))
        setattr(parser.values, option.dest, value)

    def _octal(option, opt_str, value, parser):
        try:
            setattr(parser.values, option.dest, int(value, 8))
        except ValueError:
            raise OptionValueError('Invalid octal umask value: %r' % value)

    parser.add_option('-a',
                      '--auth',
                      action='callback',
                      type='string',
                      metavar='DIGESTAUTH',
                      callback=_auth_callback,
                      callback_args=(DigestAuthentication, ),
                      help='[projectdir],[htdigest_file],[realm]')
    parser.add_option('--basic-auth',
                      action='callback',
                      type='string',
                      metavar='BASICAUTH',
                      callback=_auth_callback,
                      callback_args=(BasicAuthentication, ),
                      help='[projectdir],[htpasswd_file],[realm]')

    parser.add_option('-p',
                      '--port',
                      action='store',
                      type='int',
                      dest='port',
                      help='the port number to bind to')
    parser.add_option('-b',
                      '--hostname',
                      action='store',
                      dest='hostname',
                      help='the host name or IP address to bind to')
    parser.add_option('--protocol',
                      action='callback',
                      type="string",
                      dest='protocol',
                      callback=_validate_callback,
                      callback_args=(('http', 'scgi', 'ajp', 'fcgi'), ),
                      help='http|scgi|ajp|fcgi')
    parser.add_option('-q',
                      '--unquote',
                      action='store_true',
                      dest='unquote',
                      help='unquote PATH_INFO (may be needed when using ajp)')
    parser.add_option('--http10',
                      action='store_false',
                      dest='http11',
                      help='use HTTP/1.0 protocol version instead of HTTP/1.1')
    parser.add_option('--http11',
                      action='store_true',
                      dest='http11',
                      help='use HTTP/1.1 protocol version (default)')
    parser.add_option('-e',
                      '--env-parent-dir',
                      action='store',
                      dest='env_parent_dir',
                      metavar='PARENTDIR',
                      help='parent directory of the project environments')
    parser.add_option(
        '--base-path',
        action='store',
        type='string',  # XXX call this url_base_path?
        dest='base_path',
        help='the initial portion of the request URL\'s "path"')

    parser.add_option('-r',
                      '--auto-reload',
                      action='store_true',
                      dest='autoreload',
                      help='restart automatically when sources are modified')

    parser.add_option('-s',
                      '--single-env',
                      action='store_true',
                      dest='single_env',
                      help='only serve a single '
                      'project without the project list',
                      default=False)

    if os.name == 'posix':
        parser.add_option('-d',
                          '--daemonize',
                          action='store_true',
                          dest='daemonize',
                          help='run in the background as a daemon')
        parser.add_option('--pidfile',
                          action='store',
                          dest='pidfile',
                          help='when daemonizing, file to which to write pid')
        parser.add_option('--umask',
                          action='callback',
                          type='string',
                          dest='umask',
                          metavar='MASK',
                          callback=_octal,
                          help='when daemonizing, file mode creation mask '
                          'to use, in octal notation (default 022)')

        try:
            import grp, pwd

            def _group(option, opt_str, value, parser):
                try:
                    value = int(value)
                except ValueError:
                    try:
                        value = grp.getgrnam(value)[2]
                    except KeyError:
                        raise OptionValueError('group not found: %r' % value)
                setattr(parser.values, option.dest, value)

            def _user(option, opt_str, value, parser):
                try:
                    value = int(value)
                except ValueError:
                    try:
                        value = pwd.getpwnam(value)[2]
                    except KeyError:
                        raise OptionValueError('user not found: %r' % value)
                setattr(parser.values, option.dest, value)

            parser.add_option('--group',
                              action='callback',
                              type='string',
                              dest='group',
                              metavar='GROUP',
                              callback=_group,
                              help='the group to run as')
            parser.add_option('--user',
                              action='callback',
                              type='string',
                              dest='user',
                              metavar='USER',
                              callback=_user,
                              help='the user to run as')
        except ImportError:
            pass

    parser.set_defaults(port=None,
                        hostname='',
                        base_path='',
                        daemonize=False,
                        protocol='http',
                        http11=True,
                        umask=022,
                        user=None,
                        group=None)
    options, args = parser.parse_args()

    if not args and not options.env_parent_dir:
        parser.error('either the --env-parent-dir option or at least one '
                     'environment must be specified')
    if options.single_env:
        if options.env_parent_dir:
            parser.error('the --single-env option cannot be used with '
                         '--env-parent-dir')
        elif len(args) > 1:
            parser.error('the --single-env option cannot be used with '
                         'more than one enviroment')
    if options.daemonize and options.autoreload:
        parser.error('the --auto-reload option cannot be used with '
                     '--daemonize')

    if options.port is None:
        options.port = {
            'http': 80,
            'scgi': 4000,
            'ajp': 8009,
            'fcgi': 8000,
        }[options.protocol]
    server_address = (options.hostname, options.port)

    # relative paths don't work when daemonized
    args = [os.path.abspath(a) for a in args]
    if options.env_parent_dir:
        options.env_parent_dir = os.path.abspath(options.env_parent_dir)
    if parser.has_option('pidfile') and options.pidfile:
        options.pidfile = os.path.abspath(options.pidfile)

    wsgi_app = TracEnvironMiddleware(dispatch_request, options.env_parent_dir,
                                     args, options.single_env)
    if auths:
        if options.single_env:
            project_name = os.path.basename(args[0])
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name)
        else:
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths)
    base_path = options.base_path.strip('/')
    if base_path:
        wsgi_app = BasePathMiddleware(wsgi_app, base_path)

    if options.protocol == 'http':

        def serve():
            addr, port = server_address
            if not addr or addr == '0.0.0.0':
                loc = '0.0.0.0:%s view at http://127.0.0.1:%s/%s' \
                       % (port, port, base_path)
            else:
                loc = 'http://%s:%s/%s' % (addr, port, base_path)

            try:
                httpd = TracHTTPServer(server_address,
                                       wsgi_app,
                                       options.env_parent_dir,
                                       args,
                                       use_http_11=options.http11)
            except socket.error as e:
                print("Error starting Trac server on %s" % loc)
                print("[Errno %s] %s" % e.args)
                sys.exit(1)

            print("Server starting in PID %s." % os.getpid())
            print("Serving on %s" % loc)
            if options.http11:
                print("Using HTTP/1.1 protocol version")
            httpd.serve_forever()
    elif options.protocol in ('scgi', 'ajp', 'fcgi'):

        def serve():
            server_cls = __import__('flup.server.%s' % options.protocol, None,
                                    None, ['']).WSGIServer
            flup_app = wsgi_app
            if options.unquote:
                from trac.web.fcgi_frontend import FlupMiddleware
                flup_app = FlupMiddleware(flup_app)
            ret = server_cls(flup_app, bindAddress=server_address).run()
            sys.exit(42 if ret else 0)  # if SIGHUP exit with status 42

    try:
        if options.daemonize:
            daemon.daemonize(pidfile=options.pidfile,
                             progname='tracd',
                             umask=options.umask)
        if options.group is not None:
            os.setgid(options.group)
        if options.user is not None:
            os.setuid(options.user)

        if options.autoreload:

            def modification_callback(file):
                print("Detected modification of %s, restarting." % file,
                      file=sys.stderr)

            autoreload.main(serve, modification_callback)
        else:
            serve()

    except OSError as e:
        print("%s: %s" % (e.__class__.__name__, e), file=sys.stderr)
        sys.exit(1)
    except KeyboardInterrupt:
        pass
示例#4
0
def main():
    args = parse_args()

    wsgi_app = TracEnvironMiddleware(dispatch_request, args.env_parent_dir,
                                     args.envs, args.single_env)
    if args.auths:
        if args.single_env:
            project_name = os.path.basename(args.envs[0])
            wsgi_app = AuthenticationMiddleware(wsgi_app, args.auths,
                                                project_name)
        else:
            wsgi_app = AuthenticationMiddleware(wsgi_app, args.auths)
    base_path = args.base_path.strip('/')
    if base_path:
        wsgi_app = BasePathMiddleware(wsgi_app, base_path)

    server_address = (args.hostname, args.port)
    if args.protocol in ('http', 'https'):

        def serve():
            addr, port = server_address
            if not addr or addr == '0.0.0.0':
                loc = '0.0.0.0:%s view at %s://127.0.0.1:%s/%s' \
                       % (port, args.protocol, port, base_path)
            else:
                loc = '%s://%s:%s/%s' % (args.protocol, addr, port, base_path)

            try:
                httpd = TracHTTPServer(server_address,
                                       wsgi_app,
                                       args.env_parent_dir,
                                       args.envs,
                                       use_http_11=args.http11)
            except socket.error as e:
                print("Error starting Trac server on %s" % loc)
                print("[Errno %s] %s" % e.args)
                sys.exit(1)

            print("Server starting in PID %s." % os.getpid())
            print("Serving on %s" % loc)
            if args.http11:
                print("Using HTTP/1.1 protocol version")
            if args.protocol == 'https':
                httpd.socket = ssl.wrap_socket(httpd.socket,
                                               server_side=True,
                                               certfile=args.certfile,
                                               keyfile=args.keyfile)
            httpd.serve_forever()
    elif args.protocol in ('scgi', 'ajp', 'fcgi'):

        def serve():
            module = 'flup.server.%s' % args.protocol
            try:
                server_cls = importlib.import_module(module).WSGIServer
            except ImportError:
                printerr("Install the flup package to use the '%s' "
                         "protocol" % args.protocol)
                sys.exit(1)
            flup_app = wsgi_app
            if args.unquote:
                from trac.web.fcgi_frontend import FlupMiddleware
                flup_app = FlupMiddleware(flup_app)
            ret = server_cls(flup_app, bindAddress=server_address).run()
            sys.exit(42 if ret else 0)  # if SIGHUP exit with status 42

    try:
        if args.daemonize:
            daemon.daemonize(pidfile=args.pidfile,
                             progname='tracd',
                             umask=args.umask)
        if args.group is not None:
            os.setgid(args.group)
        if args.user is not None:
            os.setuid(args.user)

        if args.auto_reload:

            def modification_callback(file):
                printerr("Detected modification of %s, restarting." % file)

            autoreload.main(serve, modification_callback)
        else:
            serve()

    except OSError as e:
        printerr("%s: %s" % (e.__class__.__name__, e))
        sys.exit(1)
    except KeyboardInterrupt:
        pass
示例#5
0
                print 'Using HTTP/1.1 protocol version'
            httpd.serve_forever()
    elif options.protocol in ('scgi', 'ajp', 'fcgi'):
        def serve():
            server_cls = __import__('flup.server.%s' % options.protocol,
                                    None, None, ['']).WSGIServer
            flup_app = wsgi_app
            if options.unquote:
                from trac.web.fcgi_frontend import FlupMiddleware
                flup_app = FlupMiddleware(flup_app)
            ret = server_cls(flup_app, bindAddress=server_address).run()
            sys.exit(42 if ret else 0) # if SIGHUP exit with status 42

    try:
        if options.daemonize:
            daemon.daemonize(pidfile=options.pidfile, progname='tracd',
                             umask=options.umask)
        if options.group is not None:
            os.setgid(options.group)
        if options.user is not None:
            os.setuid(options.user)

        if options.autoreload:
            def modification_callback(file):
                print >> sys.stderr, 'Detected modification of %s, ' \
                                     'restarting.' % file
            autoreload.main(serve, modification_callback)
        else:
            serve()

    except OSError, e:
        print >> sys.stderr, '%s: %s' % (e.__class__.__name__, e)
示例#6
0
def main():
    from optparse import OptionParser, OptionValueError

    parser = OptionParser(usage="usage: %prog [options] [projenv] ...", version="%%prog %s" % VERSION)

    auths = {}

    def _auth_callback(option, opt_str, value, parser, cls):
        info = value.split(",", 3)
        if len(info) != 3:
            raise OptionValueError(u"Nombre de parametres incorrects pour %s" % option)

        env_name, filename, realm = info
        if env_name in auths:
            print >>sys.stderr, "Ignoring duplicate authentication option for " "project: %s" % env_name
        else:
            auths[env_name] = cls(filename, realm)

    def _validate_callback(option, opt_str, value, parser, valid_values):
        if value not in valid_values:
            raise OptionValueError("%s must be one of: %s, not %s" % (opt_str, "|".join(valid_values), value))
        setattr(parser.values, option.dest, value)

    parser.add_option(
        "-a",
        "--auth",
        action="callback",
        type="string",
        metavar="DIGESTAUTH",
        callback=_auth_callback,
        callback_args=(DigestAuthentication,),
        help="[projectdir],[htdigest_file],[realm]",
    )
    parser.add_option(
        "--basic-auth",
        action="callback",
        type="string",
        metavar="BASICAUTH",
        callback=_auth_callback,
        callback_args=(BasicAuthentication,),
        help="[projectdir],[htpasswd_file],[realm]",
    )

    parser.add_option("-p", "--port", action="store", type="int", dest="port", help="the port number to bind to")
    parser.add_option(
        "-b", "--hostname", action="store", dest="hostname", help="the host name or IP address to bind to"
    )
    parser.add_option(
        "--protocol",
        action="callback",
        type="string",
        dest="protocol",
        callback=_validate_callback,
        callback_args=(("http", "scgi", "ajp"),),
        help="http|scgi|ajp",
    )
    parser.add_option(
        "-e",
        "--env-parent-dir",
        action="store",
        dest="env_parent_dir",
        metavar="PARENTDIR",
        help="parent directory of the project environments",
    )
    parser.add_option(
        "--base-path", action="store", type="string", dest="base_path", help="base path"  # XXX call this url_base_path?
    )

    parser.add_option(
        "-r",
        "--auto-reload",
        action="store_true",
        dest="autoreload",
        help="restart automatically when sources are modified",
    )

    parser.add_option(
        "-s",
        "--single-env",
        action="store_true",
        dest="single_env",
        help="only serve a single " "project without the project list",
        default=False,
    )

    if os.name == "posix":
        parser.add_option(
            "-d", "--daemonize", action="store_true", dest="daemonize", help="run in the background as a daemon"
        )
        parser.add_option(
            "--pidfile", action="store", dest="pidfile", help="When daemonizing, file to which to write pid"
        )

    parser.set_defaults(port=None, hostname="", base_path="", daemonize=False, protocol="http")
    options, args = parser.parse_args()

    if not args and not options.env_parent_dir:
        parser.error("either the --env-parent-dir option or at least one " "environment must be specified")
    if options.single_env and len(args) > 1:
        parser.error("the --single-env option cannot be used with more " "than one enviroment")

    if options.port is None:
        options.port = {"http": 80, "scgi": 4000, "ajp": 8009}[options.protocol]
    server_address = (options.hostname, options.port)

    wsgi_app = TracEnvironMiddleware(dispatch_request, options.env_parent_dir, args, options.single_env)
    if auths:
        if options.single_env:
            project_name = os.path.basename(os.path.normpath(args[0]))
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name)
        else:
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths)
    base_path = options.base_path.strip("/")
    if base_path:
        wsgi_app = BasePathMiddleware(wsgi_app, base_path)

    if options.protocol == "http":

        def serve():
            httpd = TracHTTPServer(server_address, wsgi_app, options.env_parent_dir, args)
            httpd.serve_forever()

    elif options.protocol in ("scgi", "ajp"):

        def serve():
            server_cls = __import__("flup.server.%s" % options.protocol, None, None, [""]).WSGIServer
            ret = server_cls(wsgi_app, bindAddress=server_address).run()
            sys.exit(ret and 42 or 0)  # if SIGHUP exit with status 42

    try:
        if os.name == "posix":
            if options.pidfile:
                options.pidfile = os.path.abspath(options.pidfile)
                if os.path.exists(options.pidfile):
                    pidfile = open(options.pidfile)
                    try:
                        pid = int(pidfile.read())
                    finally:
                        pidfile.close()

                    try:
                        # signal the process to see if it is still running
                        os.kill(pid, 0)
                    except OSError, e:
                        if e.errno != errno.ESRCH:
                            raise
                    else:
                        sys.exit("tracd is already running with pid %s" % pid)
                realserve = serve

                def serve():
                    try:
                        pidfile = open(options.pidfile, "w")
                        try:
                            pidfile.write(str(os.getpid()))
                        finally:
                            pidfile.close()
                        realserve()
                    finally:
                        if os.path.exists(options.pidfile):
                            os.remove(options.pidfile)

            if options.daemonize:
                daemon.daemonize()

        if options.autoreload:

            def modification_callback(file):
                print >>sys.stderr, "Detected modification of %s, restarting." % file

            autoreload.main(serve, modification_callback)
        else:
            serve()
示例#7
0
def main():
    from optparse import OptionParser, OptionValueError
    parser = OptionParser(usage='usage: %prog [options] [projenv] ...',
                          version='%%prog %s' % VERSION)

    auths = {}

    def _auth_callback(option, opt_str, value, parser, cls):
        info = value.split(',', 3)
        if len(info) != 3:
            raise OptionValueError(u"Nombre de parametres incorrects pour %s" %
                                   option)

        env_name, filename, realm = info
        if env_name in auths:
            print >>sys.stderr, 'Ignoring duplicate authentication option for ' \
                                'project: %s' % env_name
        else:
            auths[env_name] = cls(filename, realm)

    def _validate_callback(option, opt_str, value, parser, valid_values):
        if value not in valid_values:
            raise OptionValueError('%s must be one of: %s, not %s' %
                                   (opt_str, '|'.join(valid_values), value))
        setattr(parser.values, option.dest, value)

    parser.add_option('-a',
                      '--auth',
                      action='callback',
                      type='string',
                      metavar='DIGESTAUTH',
                      callback=_auth_callback,
                      callback_args=(DigestAuthentication, ),
                      help='[projectdir],[htdigest_file],[realm]')
    parser.add_option('--basic-auth',
                      action='callback',
                      type='string',
                      metavar='BASICAUTH',
                      callback=_auth_callback,
                      callback_args=(BasicAuthentication, ),
                      help='[projectdir],[htpasswd_file],[realm]')

    parser.add_option('-p',
                      '--port',
                      action='store',
                      type='int',
                      dest='port',
                      help='the port number to bind to')
    parser.add_option('-b',
                      '--hostname',
                      action='store',
                      dest='hostname',
                      help='the host name or IP address to bind to')
    parser.add_option('--protocol',
                      action='callback',
                      type="string",
                      dest='protocol',
                      callback=_validate_callback,
                      callback_args=(('http', 'scgi', 'ajp'), ),
                      help='http|scgi|ajp')
    parser.add_option('-e',
                      '--env-parent-dir',
                      action='store',
                      dest='env_parent_dir',
                      metavar='PARENTDIR',
                      help='parent directory of the project environments')
    parser.add_option(
        '--base-path',
        action='store',
        type='string',  # XXX call this url_base_path?
        dest='base_path',
        help='base path')

    parser.add_option('-r',
                      '--auto-reload',
                      action='store_true',
                      dest='autoreload',
                      help='restart automatically when sources are modified')

    parser.add_option('-s',
                      '--single-env',
                      action='store_true',
                      dest='single_env',
                      help='only serve a single '
                      'project without the project list',
                      default=False)

    if os.name == 'posix':
        parser.add_option('-d',
                          '--daemonize',
                          action='store_true',
                          dest='daemonize',
                          help='run in the background as a daemon')
        parser.add_option('--pidfile',
                          action='store',
                          dest='pidfile',
                          help='When daemonizing, file to which to write pid')

    parser.set_defaults(port=None,
                        hostname='',
                        base_path='',
                        daemonize=False,
                        protocol='http')
    options, args = parser.parse_args()

    if not args and not options.env_parent_dir:
        parser.error('either the --env-parent-dir option or at least one '
                     'environment must be specified')
    if options.single_env and len(args) > 1:
        parser.error('the --single-env option cannot be used with more '
                     'than one enviroment')

    if options.port is None:
        options.port = {
            'http': 80,
            'scgi': 4000,
            'ajp': 8009,
        }[options.protocol]
    server_address = (options.hostname, options.port)

    wsgi_app = TracEnvironMiddleware(dispatch_request, options.env_parent_dir,
                                     args, options.single_env)
    if auths:
        if options.single_env:
            project_name = os.path.basename(os.path.normpath(args[0]))
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name)
        else:
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths)
    base_path = options.base_path.strip('/')
    if base_path:
        wsgi_app = BasePathMiddleware(wsgi_app, base_path)

    if options.protocol == 'http':

        def serve():
            httpd = TracHTTPServer(server_address, wsgi_app,
                                   options.env_parent_dir, args)
            httpd.serve_forever()
    elif options.protocol in ('scgi', 'ajp'):

        def serve():
            server_cls = __import__('flup.server.%s' % options.protocol, None,
                                    None, ['']).WSGIServer
            ret = server_cls(wsgi_app, bindAddress=server_address).run()
            sys.exit(ret and 42 or 0)  # if SIGHUP exit with status 42

    try:
        if os.name == 'posix':
            if options.pidfile:
                options.pidfile = os.path.abspath(options.pidfile)
                if os.path.exists(options.pidfile):
                    pidfile = open(options.pidfile)
                    try:
                        pid = int(pidfile.read())
                    finally:
                        pidfile.close()

                    try:
                        # signal the process to see if it is still running
                        os.kill(pid, 0)
                    except OSError, e:
                        if e.errno != errno.ESRCH:
                            raise
                    else:
                        sys.exit("tracd is already running with pid %s" % pid)
                realserve = serve

                def serve():
                    try:
                        pidfile = open(options.pidfile, 'w')
                        try:
                            pidfile.write(str(os.getpid()))
                        finally:
                            pidfile.close()
                        realserve()
                    finally:
                        if os.path.exists(options.pidfile):
                            os.remove(options.pidfile)

            if options.daemonize:
                daemon.daemonize()

        if options.autoreload:

            def modification_callback(file):
                print>>sys.stderr, 'Detected modification of %s, restarting.' \
                                   % file

            autoreload.main(serve, modification_callback)
        else:
            serve()