From 75b49d8bf699e16e5081e15115ca9d3d8dc35b76 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 7 Nov 2008 22:56:56 +0100 Subject: [PATCH] fastcgi: Add init script for fastcgi processes. This script will for now ignore its command line arguments and always restart all scripts. This should be improved in the future. --- etc/init.d/fastcgi | 134 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100755 etc/init.d/fastcgi diff --git a/etc/init.d/fastcgi b/etc/init.d/fastcgi new file mode 100755 index 0000000..6882ff9 --- /dev/null +++ b/etc/init.d/fastcgi @@ -0,0 +1,134 @@ +#!/usr/bin/python +import os +import re +import pwd +import grp +import shutil +import stat + +ROOT_DIR="/data/www" + +# SITES = [(sitename, application_list)] +# application_list = [application_name, (application_name, command, ...)] +# Here, sitename is the name of the site. This folder name should exist below ROOT_DIR and +# is also used below SOCKET_DIR. The site name is also translated to a user and +# group name by replacing dots by dashes and prepending USER_PREFIX and +# GROUP_PREFIX. +# +# application_list specifies the applications to start for this site. These can +# be generic (when only application_name is given), in which case the command +# is looked up in APPLICATIONS using the application_name. For a site-specific +# application, command is the command that should be run. It will be prefixed +# with the site's root dir, if is not an absolute path. + + +SITES=[ +# ('stderr.nl', ['php']), +# ('stdin.nl', ['php']), + ('stdout.nl', ['php']), +# ('evolution-events.nl', ['php']), #, ('xerxes', 'applications/xerxes/manage.py runfcgi'), ('wipi', 'applications/wipi/wipi.fcgi')]), +# ('stdio.flexvps.nl', ['php']), +# ('foresightsecurity.nl', ['php']), +] + +# Generic applications that can be run for any site +# Maps application_name to application_command. application_command will be +# prefixed with the site's root dir, if it is not an absolute path. +APPLICATIONS={"php": "/usr/bin/php-cgi"} + +# Kill these procs before starting new ones. Only processes of these names that +# are run by the sites in SITES are killed. This is a bit hackish, we should +# really be using pidfiles... +KILL_PROCS=['php-cgi', 'manage.py'] + +## ABSOLUTE path to the spawn-fcgi binary +SPAWNFCGI="/usr/bin/spawn-fcgi" + +## Dir in which to create the UNIX sockets to listen on +SOCKET_DIR="%s/var/fcgi" % (ROOT_DIR) + +## number of PHP children to spawn +PHP_FCGI_CHILDREN=2 + +## maximum number of requests a single PHP process can serve before it is restarted +PHP_FCGI_MAX_REQUESTS=1000 + +# The user to run as, will be prefixed to the sitename +USER_PREFIX="httpd-" +# The group to run as. +SCRIPT_GROUP="httpd-users" +# The group that should be able to use the sockets created +HTTPD_GROUP="www-data" + +# Will be postfixed to the site's root and exported in the PHPRC variable. +PHPRC_DIR="conf" + +#### END OF CONFIG #### + +for (site, apps) in SITES: + site_name = re.sub('\.', '-', site) + + ## switch to the following user / group + user_id = "%s%s" % (USER_PREFIX, site_name) + + # Find the site dir + site_dir = os.path.join(ROOT_DIR, site) + socket_dir = os.path.join(SOCKET_DIR, site_name) + + if not site_dir: + raise Exception("Site dir does not exist: %s" % (site_dir)) + + + # Kill existing processes first + for procname in KILL_PROCS: + os.system('killall --user %s %s' % (user_id, procname)) + + # Remove old sockets + if os.path.exists(socket_dir): + shutil.rmtree(socket_dir) + + # Create dir for sockets. Make owning group root and set group write + # permissions, so the mask field in the acl will not block out anything. + os.makedirs(socket_dir) + os.chown(socket_dir, pwd.getpwnam(user_id)[2], grp.getgrnam(HTTPD_GROUP)[2]) + #os.chmod(socket_dir, stat.S_IRWXU) + + for app in apps: + # Unpack app tuple or lookup app command in APPLICATIONS + if isinstance(app, tuple): + if len(app) == 2: + (app_name, app_command) = app + else: + raise Exception("Wrong number of elements in site tuple: %s", app) + else: + app_name = app + app_command = APPLICATIONS[app_name] + + # Prefix with site dir if not an absolute path + if not os.path.isabs(app_command): + app_command = os.path.join(site_dir, app_command) + + # Create socket filename + socket = os.path.join(socket_dir, app_name) + + # Build the command + # TODO: Wrap this in env to clear up the environment + spawnfcgi = '%s -s "%s" -u "%s" -g "%s"' % (SPAWNFCGI, socket, user_id, SCRIPT_GROUP) + fcgiapp = ' -- %s' % (app_command) + + if app_name == 'php': + os.environ['PHP_FCGI_MAX_REQUESTS'] = str(PHP_FCGI_MAX_REQUESTS) + phprc = os.path.join(site_dir, PHPRC_DIR, 'php.ini') + if os.path.exists(phprc): + #os.environ['PHPRC'] = phprc + fcgiapp += ' -c %s' % (phprc) + spawnfcgi += ' -C %s' % (PHP_FCGI_CHILDREN) + + + print spawnfcgi + fcgiapp + os.system(spawnfcgi + fcgiapp) + + # Ensure www-data can write to the socket :-S + # Spawn-fcgi explicitely chmods the socket after creation, very + # annoying + os.chmod(socket, stat.S_IRWXU | stat.S_IRWXG) -- 2.30.2