[ACCEPTED]-PHP Check Process ID-process

Accepted answer
Score: 19

In linux, you would look at /proc.

return file_exists( "/proc/$pid" );

In Windows 11 you could shell_exec() tasklist.exe, and 10 that would find a matching process id:

$processes = explode( "\n", shell_exec( "tasklist.exe" ));
foreach( $processes as $process )
{
     if( strpos( "Image Name", $process ) === 0
       || strpos( "===", $process ) === 0 )
          continue;
     $matches = false;
     preg_match( "/(.*?)\s+(\d+).*$/", $process, $matches );
     $pid = $matches[ 2 ];
}

I 9 believe what you want to do is maintain 8 a PID file. In the daemons I've written, they 7 check a config file, look for an instance 6 of a pid file, get the pid out of the pid 5 file, check to see if /proc/$pid exists, and 4 if not, delete the pid file.

   if( file_exists("/tmp/daemon.pid"))
   {
       $pid = file_get_contents( "/tmp/daemon.pid" );
       if( file_exists( "/proc/$pid" ))
       {
           error_log( "found a running instance, exiting.");
           exit(1);
       }
       else
       {
           error_log( "previous process exited without cleaning pidfile, removing" );
           unlink( "/tmp/daemon.pid" );
       }
   }
   $h = fopen("/tmp/daemon.pid", 'w');
   if( $h ) fwrite( $h, getmypid() );
   fclose( $h );

Process IDs 3 are granted by the OS and one cannot reserve 2 a process id. You would write your daemon 1 to respect the pid file.

Score: 6

A better way to accomplish this would be 6 to use a pid or a lock file. Simply check 5 for the existence of the pid file, create 4 it as necessary, and populate it with your 3 running pid.

<?
  class pidfile {
    private $_file;
    private $_running;

    public function __construct($dir, $name) {
      $this->_file = "$dir/$name.pid";

      if (file_exists($this->_file)) {
        $pid = trim(file_get_contents($this->_file));
        if (posix_kill($pid, 0)) {
          $this->_running = true;
        }
      }

      if (! $this->_running) {
        $pid = getmypid();
        file_put_contents($this->_file, $pid);
      }
    }

    public function __destruct() {
      if ((! $this->_running) && file_exists($this->_file)) {
        unlink($this->_file);
      }
    }

    public function is_already_running() {
      return $this->_running;
    }
  }
?>

And use it as follows:

<?
  $pidfile = new pidfile('/tmp', 'myscript');
  if($pidfile->is_already_running()) {
    echo "Already running.\n";
    exit;
  } else {
    echo "Started...\n";
  }
?>

There's 2 not much error checking here, but a quick 1 run shows this works on my system.

Score: 4

For checking if a PID exist on a windows 15 machine i use:

function pidExists($pid)
{
    exec('TASKLIST /NH /FO "CSV" /FI "PID eq '.$pid.'"', $outputA );
    $outputB = explode( '","', $outputA[0] );
    return isset($outputB[1])?true:false;
}

Note that $outputB[0] contains a messages 14 that pid can't be found, if the pid indeed 13 doesn't exists! So to validate i use the 12 second argument.

EDIT:

To expand on this, its 11 also possible to dynamically spawn scripts 10 within windows in the background using powershell 9 like so:

    // this function builds an argument list to parse into the newly spawned script. 
    // which can be accessed through the superglobal  global $argv;
    function buildArgList( array $arguments){
     return ' '. implode(' ', $arguments) .' ';
    }

    $arguments = buildArgList(['argument1','argument2','argument3']);
    $windowstyle = 'normal'; // or you can use hidden to hide the CLI

    pclose(popen("powershell start-process -FilePath '" . PHP_BINARY . "' -ArgumentList '-f\"" . $file . " " . $arguments . "\"' -WindowStyle " . $windowstyle,"r"));   

The script you spawn can then use: cli_set_process_title to 8 set that process's title to some unique 7 hash.

within the parent that spawned the 6 child process you can use the following 5 code to find that process within the tasklist 4 using its windowtitle searching for the 3 uniquehash.

exec('TASKLIST /NH /FO "CSV" /FI "windowtitle eq ' . escapeshellarg($uniquehash) . '"', $output );

When combined with a database 2 you can essentially build a workermanager communicating 1 between different php scripts.

Score: 1

No you cannot change any processes pid. It 2 is assigned by the kernel and is part of 1 the kernel's data structures

Score: 0

As others have said, you cannot change the 22 process id - it is assigned and entirely 21 manged by the kernel of the OS. Additionally, you 20 have not said if this is command-line or 19 web-server based: if it's the latter you 18 may not even be getting the pid of your 17 script.

The manual page for getmypid() contains some examples of "optimistic" locking. I 16 use the word optimisitc as PHP is never 15 ever going to approach the likes of an asp.net 14 web application where you have a true threaded 13 environment with shared/static classes and 12 thus Singleton's to use/abuse. Basically 11 you have the option of:

  • Touching a "lock file" on the file-system somewhere. Your script then checks if that file exists: if it does, terminate, otherwise, touch that file and carry on processing
  • Setting a database based flag to say the script is running. As above, but use a db table/field to mark a script as running.

Both of these rely 10 on the script terminating correctly (as 9 the last step would be to remove the lock 8 file/db flag). If a script crashes for 7 any reason (or the machine itself), you 6 can be left with a manual tidy-up process 5 to remove the flag. There is no easy solution 4 for this, but one avenue to explore would 3 be to then look at date-stamping the lock, with 2 an arbitary "if older than X, the last 1 run must have crashed" approach.

Score: 0

Don't forget also that you can access shell 3 commands via backticks (`), which would 2 give you access to the standard *nix tools 1 for working with pids.

source: http://www.php.net/manual/en/language.operators.execution.php

More Related questions