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

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.

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.

Getting Things Done with Tracks

I've been using an OmniOutliner document to track tasks and hopefully prevent things from slipping through the cracks. It works quite well, especially when combined with kGTD to help prioritize and filter tasks as they start to pile up, but it's limited to a file on one computer. So, I can't easily add stuff from my Powerbook at home. And I can't access it when I'm not sitting in front of my G5. Sure, I can sync the file, and export it to the web, and print it, and sync it to my iPod, and to iCal, etc… but that's a pain, and not bulletproof.

I was doing some Googling for other "getting things done" packages, and found a reference to Tracks. It's a Ruby on Rails app that provides the streamlined context/project interface on top of a plain to-do list. So, I threw a copy of it on my Dreamhost server (it's got all of these bells and whistles just sitting idle, which would be a shame). It Just Worked. I had to refer to the Dreamhost wiki to see how to best set up a Rails app to be served by Apache, but that was pretty darned easy.

The hardest part of the whole install was figuring htf to create an account – open the "signup" url, and you're good to go.

Performance is a bit lacking, but the entire network is feeling slowish today. It's not fatally slow, anyway. I've added in most of my current projects, and it's already helped me to see at a glance what's the most important set of tasks to be working on.

And it's the first non-Drupal tool I've installed in a while, which is a welcome change 🙂

Tracks - Getting Things Done in RailsTracks – Getting Things Done in Rails

Update: Bonus. Now I’ve got multiple RSS feeds to keep me up to date on upcoming important tasks and deadlines…

I've been using an OmniOutliner document to track tasks and hopefully prevent things from slipping through the cracks. It works quite well, especially when combined with kGTD to help prioritize and filter tasks as they start to pile up, but it's limited to a file on one computer. So, I can't easily add stuff from my Powerbook at home. And I can't access it when I'm not sitting in front of my G5. Sure, I can sync the file, and export it to the web, and print it, and sync it to my iPod, and to iCal, etc… but that's a pain, and not bulletproof.

I was doing some Googling for other "getting things done" packages, and found a reference to Tracks. It's a Ruby on Rails app that provides the streamlined context/project interface on top of a plain to-do list. So, I threw a copy of it on my Dreamhost server (it's got all of these bells and whistles just sitting idle, which would be a shame). It Just Worked. I had to refer to the Dreamhost wiki to see how to best set up a Rails app to be served by Apache, but that was pretty darned easy.

The hardest part of the whole install was figuring htf to create an account – open the "signup" url, and you're good to go.

Performance is a bit lacking, but the entire network is feeling slowish today. It's not fatally slow, anyway. I've added in most of my current projects, and it's already helped me to see at a glance what's the most important set of tasks to be working on.

And it's the first non-Drupal tool I've installed in a while, which is a welcome change 🙂

Tracks - Getting Things Done in RailsTracks – Getting Things Done in Rails

Update: Bonus. Now I’ve got multiple RSS feeds to keep me up to date on upcoming important tasks and deadlines…