#!/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', ('trac', 'applications/trac/trac.fcgi')]), # ('stdin.nl', ['php']), ('stdout.nl', ['php']), ('ninniach.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) # Pass the site dir to all fastcgi processes os.environ['SITE_DIR'] = site_dir 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)