| 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 | |