Ticket #1736: django-management-fastcgi.diff

File django-management-fastcgi.diff, 7.5 KB (added by jcrasta@…, 18 years ago)

FastCGI patch (use patch -pO in magic-removal )

  • core/management.py

     
    997997    autoreload.main(inner_run)
    998998runserver.args = '[optional port number, or ipaddr:port]'
    999999
     1000FASTCGI_HELP = r"""runfcgi:
     1001  Run this project as a fastcgi application. To do this, the
     1002  flup package from http://www.saddi.com/software/flup/ is
     1003  required.
     1004
     1005Usage:
     1006   django-admin.py runfcgi --setttings=yourproject.settings [fcgi settings]
     1007   manage.py runfcgi [fcgi settings]
     1008     
     1009Optional Fcgi settings: (setting=value)
     1010  host=HOSTNAME        hostname to listen on..
     1011  port=PORTNUM         port to listen on.
     1012  socket=FILE          UNIX socket to listen on.
     1013  method=IMPL          prefork or threaded (default prefork)
     1014  maxspare=NUMBER      max number of spare processes to keep running.
     1015  minspare=NUMBER      min number of spare processes to prefork.
     1016  maxchildren=NUMBER   hard limit number of processes in prefork mode.
     1017  daemonize=BOOL       whether to detach from terminal.
     1018  pidfile=FILE         write the spawned process-id to this file.
     1019  workdir=DIRECTORY    change to this directory when daemonizing
     1020
     1021Examples:
     1022  Run a "standard" fastcgi process on a file-descriptor
     1023  (for webservers which spawn your processes for you)
     1024    $ manage.py runfcgi method=threaded
     1025
     1026  Run a fastcgi server on a TCP host/port
     1027    $ manage.py runfcgi method=prefork host=127.0.0.1 port=8025
     1028
     1029  Run a fastcgi server on a UNIX domain socket (posix platforms only)
     1030    $ manage.py runfcgi method=prefork socket=/tmp/fcgi.sock
     1031
     1032  Run a fastCGI as a daemon and write the spawned PID in a file
     1033    $ manage.py runfcgi socket=/tmp/fcgi.sock method=prefork \
     1034        daemonize=true pidfile=/var/run/django-fcgi.pid
     1035 
     1036"""
     1037
     1038def fastcgi_help(message = None):
     1039    print FASTCGI_HELP
     1040    if message:
     1041        print message
     1042    return False
     1043
     1044FASTCGI_OPTIONS = {
     1045    'host': None,
     1046    'port': None,
     1047    'socket': None,
     1048    'method': 'fork',
     1049    'daemonize': None,
     1050    'workdir': '.',
     1051    'pidfile': None,
     1052    'maxspare': 5,
     1053    'minspare': 2,
     1054    'maxchildren': 50,
     1055}
     1056
     1057def runfastcgi(argset):
     1058    """Run this project as a FastCGI application. requires flup."""
     1059    options = FASTCGI_OPTIONS.copy()
     1060    for x in argset:
     1061        if "=" in x:
     1062            k, v = x.split('=', 1)
     1063        else:
     1064            k,v = x, True
     1065        options[k.lower()] = v
     1066
     1067    if "help" in options:
     1068        return fastcgi_help()
     1069
     1070    try:
     1071        import flup
     1072    except ImportError, e:
     1073        print >> sys.stderr, "ERROR: %s" % e
     1074        print >> sys.stderr, "  Unable to load the flup package.  In order to run django"
     1075        print >> sys.stderr, "  as a FastCGI application, you will need to get flup from"
     1076        print >> sys.stderr, "  http://www.saddi.com/software/flup/   If you have flup already"
     1077        print >> sys.stderr, "  installed, then make sure you have it in your pythonpath."
     1078        return False
     1079       
     1080    if options['method'] in ('prefork', 'fork'):
     1081        from flup.server.fcgi_fork import WSGIServer
     1082        wsgi_opts = dict(
     1083            maxSpare = int(options["maxspare"]),
     1084            minSpare = int(options["minspare"]),
     1085            maxChildren = int(options["maxchildren"]),
     1086        )
     1087    elif options['method'] in ('thread', 'threaded'):
     1088        from flup.server.fcgi import WSGIServer
     1089        wsgi_opts = {}
     1090    else:
     1091        return fastcgi_help("ERROR: implementation must be one of prefork or thread")
     1092
     1093    # prep up and go
     1094    from django.core.handlers.wsgi import WSGIHandler
     1095
     1096    if options["host"] and options["port"] and not options["socket"]:
     1097        wsgi_opts['bindAddress'] = (options["host"], int(options["port"]))
     1098    elif options["socket"] and not options["host"] and not options["port"]:
     1099        wsgi_opts['bindAddress'] = options["socket"]
     1100    elif not options["socket"] and not options["host"] and not options["port"]:
     1101        wsgi_opts['bindAddress'] = None
     1102    else:
     1103        return fastcgi_help("invalid combination of host,port,socket.")
     1104
     1105    if options["daemonize"] is None:
     1106        # default to daemonizing if we are running as a daemon process
     1107        daemonize = (wsgi_opts['bindAddress'] is not None)
     1108    else:
     1109        if options["daemonize"].lower() in ('true', 'yes', 't'):
     1110            daemonize = True
     1111        elif options["daemonize"].lower() in ('false', 'no', 'f'):
     1112            daemonize = False
     1113        else:
     1114            return fastcgi_help("ERROR: invalid option for daemonize parameter")
     1115   
     1116    if daemonize:
     1117        from django.utils.daemonize import become_daemon
     1118        become_daemon(ourHomeDir=options["workdir"])
     1119
     1120    if options["pidfile"]:
     1121        fp = open(options["pidfile"], "w")
     1122        fp.write("%d\n" % os.getpid())
     1123        fp.close()
     1124
     1125    WSGIServer(WSGIHandler(), **wsgi_opts).run()
     1126
     1127
     1128
     1129runfastcgi.args = '[various KEY=val options, run `runfcgi help` for help]'
     1130
    10001131def createcachetable(tablename):
    10011132    "Creates the table needed to use the SQL cache backend"
    10021133    from django.db import backend, connection, transaction, get_creation_module, models
     
    10631194    'inspectdb': inspectdb,
    10641195    'install': install,
    10651196    'reset': reset,
     1197    'runfcgi': runfastcgi,
    10661198    'runserver': runserver,
    10671199    'shell': run_shell,
    10681200    'sql': get_sql_create,
     
    11781310            except ValueError:
    11791311                addr, port = '', args[1]
    11801312        action_mapping[action](addr, port)
     1313    elif action == 'runfcgi':
     1314        action_mapping[action](args[1:])
    11811315    else:
    11821316        from django.db import models
    11831317        try:
  • utils/daemonize.py

     
     1import os
     2import sys
     3
     4if os.name == 'posix':
     5
     6        def become_daemon(ourHomeDir='.',outLog='/dev/null',errLog='/dev/null'):
     7                """
     8                Robustly turn us into a UNIX daemon, running in ourHomeDir.
     9                Modelled after the original code of this module and some
     10                sample code from the net.
     11                """
     12
     13                # first fork
     14                try:
     15                        if os.fork() > 0:
     16                                sys.exit(0)     # kill off parent
     17                except OSError, e:
     18                        sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror))
     19                        sys.exit(1)
     20                os.setsid()
     21                os.chdir(ourHomeDir)
     22                os.umask(0)
     23                # second fork
     24                try:
     25                        if os.fork() > 0:
     26                                sys.exit(0)
     27                except OSError, e:
     28                        sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror))
     29                        sys.exit(1)
     30
     31                si = open('/dev/null', 'r')
     32                so = open(outLog, 'a+', 0)
     33                se = open(errLog, 'a+', 0)
     34                os.dup2(si.fileno(), sys.stdin.fileno())
     35                os.dup2(so.fileno(), sys.stdout.fileno())
     36                os.dup2(se.fileno(), sys.stderr.fileno())
     37
     38else:
     39
     40        def become_daemon(ourHomeDir='.',outLog=None,errLog=None):
     41                """
     42                If we are not running under a POSIX system, just simulate
     43                the daemon mode by doing redirections and directory changeing
     44                """
     45
     46                os.chdir(ourHomeDir)
     47                os.umask(0)
     48                sys.stdin.close()
     49                sys.stdout.close()
     50                sys.stderr.close()
     51                if errLog and outLog:
     52                        sys.stderr=open (errLog, 'a', 0)
     53                        sys.stdout=open (outLog, 'a', 0)
     54                elif errLog:
     55                        sys.stderr=open (errLog, 'a', 0)
     56                        sys.stdout=NullDevice ()
     57                elif outLog:
     58                        sys.stdout=open (outLog, 'a', 0)
     59                        sys.stderr=NullDevice ()
     60                else:
     61                        sys.stdout = NullDevice()
     62                        sys.stderr = NullDevice()
     63
     64        class NullDevice:
     65                """
     66                A substitute for stdout and stderr that writes to nowhere.
     67                This is a substitute for /dev/null
     68                """
     69       
     70                def write(self, s):
     71                        pass
Back to Top