Script for running Cron on all sites in a shared Drupal instance

January 1, 2007 · 4 comments

in Uncategorized

After realizing that the sympal_scripts were silently failing to properly call cron.php on sites served from subdirectories on a shared Drupal multisite instance, I rolled up my sleeves to build a script that actually worked. What I’ve come up with works, but is likely not the cleanest or most efficient way of doing things. But it works. Which is better than the solution I had earlier today.

I also took the chance to get more familiar with Ruby. I could have come up with a shell script solution, but I wanted the flexibility to more easily extend the script as needed. And I wanted the chance to play with Ruby in a non-Hello-World scenario.

Here’s the code:

#!/usr/local/bin/ruby

# Drupal multisite hosting auto cron.php runner
# Initial draft version by D'Arcy Norman dnorman@darcynorman.net
# URL goes here
# Idea and some code from a handy page by (some unidentified guy) at http://whytheluckystiff.net/articles/wearingRubySlippersToWork.html

require 'net/http'

# this script assumes that $base_url has been properly set in each site's settings.php file.
# further, it assumes that it is at the START of a line, with spacing as follows:
# $base_url = 'http://mywonderfuldrupalserver.com/site';
# also further, it assumes there is no comment before nor after the content of that line.

# customize this variable to point to your Drupal directory
drupalsitesdir = '/usr/www/drupal' # no trailing slash

Dir[drupalsitesdir + '/sites/**/*.php'].each do |path|
  File.open(path) do |f|
    f.grep( /^\$base_url = / ) do |line|
      line = line.strip();
      baseurl = line.gsub('$base_url = \'', '')
      baseurl = baseurl.gsub('\';', '')
      baseurl = baseurl.gsub('  // NO trailing slash!', '')

      if !baseurl.empty?
        cronurl = baseurl + "/cron.php"
        puts cronurl

        if !cronurl.empty?
          url = URI.parse(cronurl)
          req = Net::HTTP::Get.new(url.path)
          res = Net::HTTP.start(url.host, url.port) {|http|http.request(req)}
          puts res.body
        end
      end
    end
  end
end

No warranty, no guarantee. It works on my servers, and on my PowerBook.

Some caveats:

  • It requires a version of Ruby more recent than what ships on MacOSX 10.3 server. Easy enough to update, following the Ruby on Rails installation instructions.
  • It requires $base_url to be set in the settings.php file for each site you want to run cron.php on automatically.
  • It requires one trivial edit to the script, telling it where Drupal lives on your machine. I might take a look at parameterizing this so it could be run more flexibily.
  • It requires cron (or something similar) to trigger the script on a regular basis.

{ 4 comments… read them below or add one }

1 Khalid January 2, 2007 at 10:39 am

Darcy,

Ruby may not be available on all systems.

Here is a shell script that does the same thing. Same assumptions as yours. It is tested too.

#!/bin/sh

if [ $# = 1 ]; then
  DRUPAL_SITES_DIR=$1/sites
  if [ -d "$DRUPAL_SITES_DIR" ]; then
    cd $DRUPAL_SITES_DIR

    for SITE in `ls -F | grep /`
    do
      FILE=${SITE}settings.php
      if [ -r "$FILE" ]; then
        URL=`grep '^\$base_url.*=' $FILE | sed -e "s/^.*http://" -e "s/[';]//g"`
        if [ "$URL" != "" ]; then
          wget -O - -q http:$URL/cron.php
        fi
      fi
    done
  fi
fi

Reply

2 dnorman January 2, 2007 at 12:00 pm

Khalid – Well, fine then. Go ahead and whip up a better, more generalizable script that will run anywhere. :-)

At least I got to play in Ruby for a bit. I’ll be switching to your script to run cron.php, though. Thanks!

Reply

3 sami khan January 2, 2007 at 2:32 pm

lol. i was thinking, c’mon now d’arcy a ruby script to power a php script?!?

Reply

4 dnorman January 2, 2007 at 2:44 pm

yeah yeah… I could have written it in C, so I could run ./configure make make install too :-) I just wanted to write the script and figured Ruby would be cool. Loosely joined and all that. It’s just firing off a curl to a web interface anyway. It could have been written in Logo :-)

Reply

Leave a Comment

Previous post:

Next post: