Thursday, December 2, 2010

Drupal Command Line Script Template

Drupal Command Line Script Template

Submitted by dale on March 23, 2009 - 11:09am

Tagged:

command line

Drupal

Drupal 5

Drupal 6

Planet Drupal

script template

scripting

There are development tasks better suited to running in a command-line script than in the Drupal web interface. The two most notable in my experience are code fragment testing, especially when exploring how an API works, and data import/export. Happily, this kind of scripting is possible with Drupal.

The PHP code shown below, created from examples seen in Planet Drupal posts, and later in the drush module, is serving me well as a command-line script template. It works in both Drupal 5 and 6.

Script Template
#!/usr/bin/env php
<?php
### Optional: up time and memory limits for long running scripts
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
ini_set('max_execution_time', 18000);
//ini_set('memory_limit', '1024M');

### REMOTE_ADDR should always be set by the server, if it is we're not running on the CLI - exit
if(isset($_SERVER['REMOTE_ADDR'])){
  print "Must be called from the command line.";
  exit(1);
}

### this should be run with this script in the top-level of a drupal install, though the
### path given to the scipt may differ. Get the directory the script is in
### and chdir to it.
//chdir(realpath(dirname(__FILE__)));
$change_to_dir_path = stristr(PHP_OS, 'WINNT') ? 'D:/www/Apache2.2/htdocs/drupal_center' : '/www/drupal_center';
chdir($change_to_dir_path);

### This script must be called with one argument:
### the site name.
if ($argc != 2){
  fwrite(STDERR, "Usage: ". $argv[0] ." SITENAME\n");
  exit(1);
}

### If you want to output to your command line console
### before Drupal bootstrap, use fopen/fwrite, not echo or print.
### This avoids the warning:
### "Warning: Cannot modify header information - headers already sent".
$stdout = fopen('php://stdout', 'w');
fwrite($stdout, "[Script Template]" . PHP_EOL);
fclose($stdout);

### Set up some server variables that are needed to
### bootstrap the correct drupal site.
$_SERVER['HTTP_HOST'] = $argv[1];
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['SCRIPT_NAME'] = '/' . basename(__FILE__);
$_SERVER['REQUEST_URI'] = $_SERVER['PHP_SELF'] = $_SERVER['SCRIPT_NAME'];
//$_SERVER['REMOTE_ADDR'] = NULL;
$_SERVER['REQUEST_METHOD'] = NULL;

### Bootstrap Drupal
include_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

### Optional: perform tasks as UID=1
$user = user_load(array('uid' => 1));

### CODE HERE
echo 'Hello World!';

Usage Notes

  • I strongly recommend using this only in a development environment and not on a production site.
  • Change the site specific variables $drupal_base_url and $username to values appropriate to your site.
  • The template code, as shown, must go in a file in the Drupal root directory. It can be moved as long as you set the working directory to the Drupal root directory (See drush module for examples).
  • If you want to output to your command line console before Drupal bootstrap, use fopen/fwrite, not echo or print. This avoids the warning: "Warning: Cannot modify header information - headers already sent". An example is provided in the script.

For those of you who might not be familiar with the Drupal Shell, or drush module, check it out before creating anything too fancy.

Running the Script

To run a script from the command line you need PHP configured to do so. Describing how to do so is outside the scope of this post. At the time of writing, the following Google search gave good results for "how to" references: Google Search: php command line. Some packages, such as XAMMP for Windows, set this up for you.

To quickly see if PHP is configured issue the command: php –v

You'll see the PHP version number if PHP is configured and an error if it isn't. It's also good to check which version of PHP is configured by default if your host or configuration supports multiple versions.

Running the script is as simple as: php my_script_name.php

For more information on PHP command line options, check out: PHP.net: Using PHP from the command line.

Acknowledgments

I'd like to acknowledge the authors of the following posts for their initial examples:

Programatically Importing Data Into Drupal

Benchmarking Drupal from the shell command line

Attachment

Size

Attachment

Size

script_template.php

679 bytes

Add new comment

Comments

I'm a huge fan of these quick

Submitted by tomchuk (not verified) on March 23, 2009 - 9:12pm.

I'm a huge fan of these quick Drupal CLI scripts to do data migration or long-running jobs. Here's the one I've honed to my liking over time. I think it was originally based on one by Steve Rude (slantview). It has the added benefit of bailing out if being hit through the web server (only letting you hit it through the command line) and being able to handle a multisite setup:

#!/usr/bin/env php

// REMOTE_ADDR should always be set by the server, if it is we're not running on the CLI - exit

if(isset($_SERVER['REMOTE_ADDR'])){

  print "Must be called from the command line.";

  exit(1);

}

// this should be run with this script in the top-level of a drupal install, though the

// path given to the scipt may differ. Get the directory the script is in

// and chdir to it.

chdir(realpath(dirname(__file__)));

// This script must be called with one argument:

// the site name.

if ($argc != 2){

  fwrite(STDERR, "Usage: ". $argv[0] ." SITENAME");

  exit(1);

}

// Set up some server variables that are needed to

// bootstrap the correct drupal site.

$_SERVER['HTTP_HOST'] = $argv[1];

$_SERVER['PHP_SELF'] = basename(__file__);

$_SERVER['REMOTE_ADDR'] = '127.0.0.1';

// Bootstrap drupal

include_once './includes/bootstrap.inc';

drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// Optional: up time and memory limits for long running scripts

set_time_limit(10000);

ini_set('memory_limit', '1024M');

// Optional: perform tasks as UID=0

global $user;

$user = user_load(array('uid' => 0));

// CODE HERE

?>

reply

Thanks

Submitted by dale on March 23, 2009 - 10:10pm.

Thanks for the script example!

I edited your example to add the closing "?>" so it would colorize.

A test to insure the script is only run from the command line is a great idea. I never bothered because my development environment is closed to the outside world (and like, I was being a little lazy :-) ), but actual code might prevent a potentially disastrous incident if the script was accidentally pushed production!

Although I didn't mention, the template in the post works fine on a multi-host configuration, as well. As with your script, it sets the $_SERVER['HTTP_HOST'] value.

No comments: