| | 1000 | FASTCGI_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 | |
| | 1005 | Usage: |
| | 1006 | django-admin.py runfcgi --setttings=yourproject.settings [fcgi settings] |
| | 1007 | manage.py runfcgi [fcgi settings] |
| | 1008 | |
| | 1009 | Optional 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 | |
| | 1021 | Examples: |
| | 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 | |
| | 1038 | def fastcgi_help(message = None): |
| | 1039 | print FASTCGI_HELP |
| | 1040 | if message: |
| | 1041 | print message |
| | 1042 | return False |
| | 1043 | |
| | 1044 | FASTCGI_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 | |
| | 1057 | def 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 | |
| | 1129 | runfastcgi.args = '[various KEY=val options, run `runfcgi help` for help]' |
| | 1130 | |