Software, Languages, PHP

PHP: One Instance

Suppose you have a script in PHP that you only ever want to only ever run one instance of.

For example:

  • Maintenance script (repair,optimise)
  • Update script (crawler)
  • Server

These types of scripts need only to be launched once, and more could be counter productive or even dangerous.

The simplest way to stop multiple instances is to check to see if the last running script is still running.

  1. function isPidRunning( $pid )
  2. {
  3.  if( $pid )
  4.  {
  5.   $cmd = "ps -p ". (int)$pid;
  6.   $ps=shell_exec( $cmd );
  7.   $ps=explode("n", $ps);
  8.   if(count($ps)>=3)
  9.   {
  10.    return true;
  11.   }
  12.  }
  13.  return false;
  14. }

  1. function pidCheck( $name, $version )
  2. {
  3.  $pid = getmypid();
  4.  if( $pid !== false )
  5.  {
  6.   $pidFile = dirname( __FILE__ ) . '/pid/' . $name . '-' . $version . '.pid';
  7.   if( file_exists( $pidFile ))
  8.   {
  9.    $oldPid = file_get_contents( $pidFile );
  10.   }
  11.   else
  12.   {
  13.    $oldPid = '';
  14.   }
  15.   if( !isPidRunning( $oldPid ) )
  16.   {
  17.    file_put_contents( $pidFile, $pid );
  18.   }
  19.   else
  20.   {
  21.    return false;
  22.   }
  23.  }
  24.  else
  25.  {
  26.   return false;
  27.  }
  28.  return true;
  29. }

Function file_put_contents() requires a minimum PHP5, however you can use PHP Compat to achieve same functionality.

  1. if( !pidCheck( $applicationName, $applicationVersion ))
  2. {
  3.  die('');
  4. }

You will need to create a folder called pid in the location of script that is running this. The pid folder will require write permission for the user calling the script.

This code can be used in multiple scripts, as long as you supply different $applicationName and/or $applicationVersion strings.

If you plan on using this code in multiple scripts, you would be best off putting the functions isPidRunning and pidCheck into a separate file and using include_once to include their functionality.

Update 22 May 2007: Minor correction to the source code

comments powered by Disqus