<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>AV-Looks: Managing dispatch.fcgi processes</title>
    <link>http://avlooks.net/articles/2006/06/15/managing-dispatch-fcgi-processed</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Watching and Wondering</description>
    <item>
      <title>Managing dispatch.fcgi processes</title>
      <description>&lt;p&gt;Rails committer &lt;a href="http://jamis.jamisbuck.org/"&gt;Jamis Buck&lt;/a&gt; recently explained in &lt;a href="http://jamis.jamisbuck.org/articles/2006/02/11/tip-textdrive-and-lighttpd"&gt;this post&lt;/a&gt; why it is important not to use static FastCGI processes on shared webservers.  &lt;a href="http://avlux.net"&gt;&lt;span class="caps"&gt;AVLUX&lt;/span&gt;&lt;/a&gt; took Jamis&amp;#8217; helpful guidance and used it as a starting point to enable all its Rails hosting customers to &lt;a href="http://www.avlux.net/cgi-bin/mojo/mojo.cgi?flavor=archive&amp;#38;id=20060601015556&amp;#38;list=ror"&gt;manage their own FastCGI processes&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;At the end of this post Jamis writes:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&amp;#8220;Note, however, that a reboot of the machine hosting your account will require you to run the spawn scripts for your applications again&#8230; I&#8217;m sure there&#8217;s a handy solution for that floating around somewhere, but I don&#8217;t know it offhand.&amp;#8221;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;At &lt;a href="http://avlux.net"&gt;&lt;span class="caps"&gt;AVLUX&lt;/span&gt;&lt;/a&gt; this is how we facilitate our Rails developers managing their own dispatch.fcgi processes, and ensuring that they all run at startup:&lt;/p&gt;


&lt;strong&gt;1)&lt;/strong&gt; Create a startup script for FastCGI in /etc/rc.d/rc.fcgi
&lt;pre&gt;
#!/bin/sh

curruser=$1
currdir=`pwd`
homeuser=`stat -c %U $currdir`
domdir=/var/www/vhosts

case $2 in
  -d)
      env=development
      specific=true
      ;;
  -t)
      env=test
      specific=true
      ;;
  -p)
      env=production
      ;;
   *)
      env=production
      ;;
esac

if [ "$curruser" = "root" ]; then
  env=production
  specific=false
fi

# Read through all domains
ls -1 $domdir | while read domain
do
  # Check to for Ruby on Rails domains
  if [ -d $domdir/$domain/rails/public ]; then
    cd $domdir/$domain/rails
    # Change to fully resolved directory (no symlinks) to keep Lighttpd happy
    railsdir=`pwd -P`
    cd $railsdir
    # Get owner of current directory, in order to start fcgi processes as that user
    owner=`stat -c %U .`
    if [ "$curruser" = "root" -o "$curruser" = "$owner" ]; then
      # Ensure that ownership is set correctly
      echo Updating owner on $domain/rails dir contents to $owner
      echo Rails dir is $railsdir
      # chown -R $owner $railsdir/*
      echo Starting dispatch.fcgi in processes in RAILS_ENV $env for $domain as user $owner...
      # Create tmp/sockets dirs if they don't exist
      if [ ! -d $railsdir/tmp ]; then
        su $owner -c "mkdir tmp" 
      fi
      if [ ! -d $railsdir/tmp/sockets ]; then
        su $owner -c "mkdir tmp/sockets" 
      fi
      sockdir=$railsdir/tmp/sockets
      # Start FastCGI processes for domain
      if [ "$curruser" = "$owner" ]; then
        RAILS_ENV=$env spawn-fcgi -f $railsdir/public/dispatch.fcgi \
-s $sockdir/$domain-fcgi-0.socket -P $sockdir/$domain-fcgi-0.pid
        RAILS_ENV=$env spawn-fcgi -f $railsdir/public/dispatch.fcgi \
-s $sockdir/$domain-fcgi-1.socket -P $sockdir/$domain-fcgi-1.pid
      else
        su $owner -c "RAILS_ENV=$env spawn-fcgi -f $railsdir/public/dispatch.fcgi \
-s $sockdir/$domain-fcgi-0.socket -P $sockdir/$domain-fcgi-0.pid" 
        su $owner -c "RAILS_ENV=$env spawn-fcgi -f $railsdir/public/dispatch.fcgi \
-s $sockdir/$domain-fcgi-1.socket -P $sockdir/$domain-fcgi-1.pid" 
      fi
      echo ------------------------------------------------------
      sleep 3

      # Now check to for Ruby on Rails subdomains
      ls -1 $domdir/$domain/subdomains | while read sub
      do
        if [ -d $domdir/$domain/subdomains/$sub/rails/public ]; then
          cd $domdir/$domain/subdomains/$sub/rails
          # Change to fully resolved directory (no symlinks) to keep Lighttpd happy
          railsdir=`pwd -P`
          cd $railsdir
          # Get owner of current directory, in order to start fcgi processes as that user
          owner=`stat -c %U .`
          # Ensure that ownership is set correctly
          echo Updating owner on $sub.$domain/rails contents to $owner
          echo Rails subdir is $railsdir
          # chown -R $owner $railsdir/*
          echo Starting dispatch.fcgi processes in RAILS_ENV $env for $sub.$domain as user $owner...
          # Create tmp/sockets dirs if they don't exist
          if [ ! -d $railsdir/tmp ]; then
            su $owner -c "mkdir tmp" 
          fi
          if [ ! -d $railsdir/tmp/sockets ]; then
            su $owner -c "mkdir tmp/sockets" 
          fi
          sockdir=$railsdir/tmp/sockets
          # Start FastCGI processes for subdomain
          if [ "$curruser" = "$owner" ]; then
            RAILS_ENV=$env spawn-fcgi -f $railsdir/public/dispatch.fcgi \
-s $sockdir/$sub.$domain-fcgi-0.socket -P $sockdir/$sub.$domain-fcgi-0.pid
            RAILS_ENV=$env spawn-fcgi -f $railsdir/public/dispatch.fcgi \
-s $sockdir/$sub.$domain-fcgi-1.socket -P $sockdir/$sub.$domain-fcgi-1.pid
          else
            su $owner -c "RAILS_ENV=$env spawn-fcgi -f $railsdir/public/dispatch.fcgi \
-s $sockdir/$sub.$domain-fcgi-0.socket -P $sockdir/$sub.$domain-fcgi-0.pid" 
            su $owner -c "RAILS_ENV=$env spawn-fcgi -f $railsdir/public/dispatch.fcgi \
-s $sockdir/$sub.$domain-fcgi-1.socket -P $sockdir/$sub.$domain-fcgi-1.pid" 
          fi
          echo ------------------------------------------------------
          sleep 3
        fi
      done
      # Start Lighttpd server by user
      /usr/local/bin/lighttpd_server start $owner
    fi
  fi
done
&lt;/pre&gt;

&lt;strong&gt;2)&lt;/strong&gt; Set up FastCGI to run as a service, by creating /etc/init.d/fcgi
&lt;pre&gt;
#!/bin/bash
#. /etc/rc.d/init.d/functions
PATH=/sbin://bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin:/usr/local/bin
prog=dispatch.fcgi
proc=dispatch.fcgi
startup=/etc/rc.d/rc.fcgi
startarg=$2
owner=`whoami`
currdir=`pwd`

start() {
      if [ "$owner" = "root" ]; then
        echo "Attempting to start $prog for all users..." 
        bash $startup $owner; echo -e "OK";
      else
        if [ "$startarg" = ""  -o "$startarg" = "-d" -o "$startarg" = "-t" ]; then
          echo "Starting $prog for user '$owner'... " 
          if `pgrep -u $owner -f $proc 1&amp;gt;/dev/null 2&amp;gt;/dev/null`; then
            bash $startup $owner $startarg; echo -e "OK";
            echo "$prog for user '$owner' is already running..." 
          else
            bash $startup $owner $startarg; echo -e "OK";
          fi
        else
          echo $"Usage: $prog {start [-d, -t] |stop|restart|status}" 
          exit 1
        fi
      fi
}
stop() {
      if [ "$owner" = "root" ]; then
        echo "Stopping $prog for all users..." 
        pkill -9 -f $proc
        echo -e "OK";
      else
        echo -n $"Stopping $prog for user '$owner'..." 
        if ! `pgrep -u $owner -f $proc 1&amp;gt;/dev/null 2&amp;gt;/dev/null`
        then
          echo "$prog for user '$owner' is not running";
        else pkill -9 -u $owner -f $proc
        echo -e "OK";
        fi
      fi
}
status() {
      if [ "$owner" = "root" ]; then
        if `pgrep -f $proc 1&amp;gt;/dev/null 2&amp;gt;/dev/null`;
        then
          echo "$proc processes running on `pgrep -d , -f $proc`";
          pgrep -f $proc -l
        else echo "$prog is not running...";
        fi
      else
        if `pgrep -u $owner -f $proc 1&amp;gt;/dev/null 2&amp;gt;/dev/null`;
        then
          echo "$proc processes for user '$owner' running on `pgrep -u $owner -d , -f $proc`";
          pgrep -u $owner -f $proc -l
        else echo "$prog for user '$owner' is not running...";
        fi
      fi
}
case "$1" in
  start)
        start
        status
        ;;
  stop)
        stop
        status
        ;;
 restart)
        stop
        start
        status
        ;;
 status)
        status
        ;;
*)
        echo $"Usage: $prog {start|stop|restart|status}" 
        exit 1
esac
&lt;/pre&gt;

&lt;strong&gt;3)&lt;/strong&gt; Add this line to /etc/rc.d/rc.local
&lt;pre&gt;
/etc/init.d/fcgi start
&lt;/pre&gt;

Of course your lighttpd.conf files must be written accordingly, e.g.
&lt;pre&gt;
server.modules = ("mod_rewrite","mod_redirect","mod_access" 
,"mod_status" 
,"mod_fastcgi" 
,"mod_proxy" 
,"mod_accesslog" 
)
var.vhosts = "/home/httpd/vhosts/" 
var.domain = "yourdomain.com" 

server.bind = domain
server.port = 4004
server.pid-file = vhosts + domain + "/var/run/lighttpd.pid" 
server.username = "username" 
server.groupname = "groupname" 
status.status-url = "/server-status" 
server.indexfiles = ( "index.html", "dispatch.fcgi" )

server.document-root = vhosts + domain + "/rails/public" 
server.error-handler-404 = "/dispatch.fcgi" 
fastcgi.server= (".fcgi" =&amp;gt; ( domain  =&amp;gt;
    ( "socket" =&amp;gt; vhosts + domain + "/rails/tmp/sockets/" + domain + "-fcgi-0.socket" ),
    ( "socket" =&amp;gt; vhosts + domain + "/rails/tmp/sockets/" + domain + "-fcgi-1.socket" )
  ) )
&lt;/pre&gt;</description>
      <pubDate>Thu, 15 Jun 2006 18:55:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:3a631c33-eeab-426d-aaea-a7413566cebd</guid>
      <author>av@avlux.net (Andrew)</author>
      <link>http://avlooks.net/articles/2006/06/15/managing-dispatch-fcgi-processed</link>
      <category>System Admin</category>
      <category>Ruby on Rails</category>
      <category>AVLUX</category>
      <category>howto</category>
      <category>sysadmin</category>
      <category>lighttpd</category>
      <category>fastcgi</category>
      <category>avlux</category>
      <trackback:ping>http://avlooks.net/articles/trackback/53</trackback:ping>
    </item>
  </channel>
</rss>
