PHP Doku:: Liefert Informationen über einen mit proc_open gestarteten Prozess - function.proc-get-status.html

Verlauf / Chronik / History: (1) anzeigen

Sie sind hier:
Doku-StartseitePHP-HandbuchFunktionsreferenzErweiterungen zur ProzesskontrolleAusführung von SystemprogrammenFunktionen zur Programmausführungproc_get_status

Ein Service von Reinhard Neidl - Webprogrammierung.

Funktionen zur Programmausführung

<<proc_close

proc_nice>>

proc_get_status

(PHP 5)

proc_get_statusLiefert Informationen über einen mit proc_open() gestarteten Prozess

Beschreibung

array proc_get_status ( resource $process )

proc_get_status() liefert Daten über einen Prozess, der unter Verwendung von proc_open() gestartet wurde.

Parameter-Liste

process

Die zu untersuchende proc_open()-Ressource.

Rückgabewerte

Im Erfolgsfall wird ein Array der gesammelten Informationen zurückgeliefert, im Fehlerfall FALSE. Das zurückgegebene Array enthält die folgenden Elemente:

Element Typ Beschreibung
command string Der Kommandostring, der an proc_open() übergeben wurde.
pid int ProzessID
running bool Ist TRUE, wenn der Prozess noch läuft, und FALSE wenn er beendet wurde.
signaled bool Ist TRUE, wenn der Child-Prozess durch ein nicht erkanntes Signal beendet wurde. Unter Windows hat das Element immer den Wert FALSE.
stopped bool Ist TRUE, wenn der Child-Prozess durch ein Signal gestoppt wurde. Unter Windows hat das Element immer den Wert FALSE.
exitcode int Der Exitcode, der vom Prozess zurückgegeben wurde (dieser ist nur aussagekräftig, wenn running FALSE ist). Nur der erste Aufruf der Funktion gibt den richtigen Wert zurück, alle weiteren Aufrufe resultieren im Wert -1.
termsig int Die Signalnummer die den Child-Prozess veranlasst hat, seine Ausführung abzubrechen (nur aussagekräftig, wenn signaled TRUE ist).
stopsig int Die Signalnummer, die den Child-Prozess veranlasst hat, seine Ausführung zu stoppen (nur aussagekräftig, wenn stopped TRUE ist).

Siehe auch

  • proc_open() - Führt ein Kommando aus und öffnet Dateizeiger für die Ein- und Ausgabe


8 BenutzerBeiträge:
- Beiträge aktualisieren...
Mark Seecof
7.09.2009 5:36
On Unix/Linux, if you change the command line you pass to proc_open() just slightly then proc_get_status() will give you the actual process-id (pid) of your child.

Suppose you wish to run the external command /usr/bin/compress to create a BSD foo.Z file.  Rather than proc_open("/usr/bin/compress /tmp/foo",...) you may invoke proc_open("exec /usr/bin/compress /tmp/foo",...) and then proc_get_status()['pid'] will be the actual pid of /usr/bin/compress.

Why?  Because the way proc_open() actually works on Unix/Linux is by starting "/bin/sh -c usercmd userargs...", e.g., "/bin/sh -c /usr/bin/compress /tmp/foo".[Note 1]  That means normally your command is the child of the shell, so the pid you retrieve with proc_get_status() is the pid of the shell (PHP's child), and you have to fumble around trying to find the pid of your command (PHP's grandchild).  But if you put "exec" in front of your command, you tell the shell to *replace itself* with your command without starting another process (technically, to exec your command without forking first).  That means your command will inherit the pid of the shell, which is the pid that proc_get_status() returns.

So if you would like the actual pid of the process running your command, just prepend "exec " to  your proc_open() command argument then retrieve the pid using proc_get_status().

This also makes proc_terminate() and proc_close() work more like you might prefer, since they will affect the actual process running your command (which will be a child process rather than a grandchild process).

[Note 1] My guess is that the PHP developers want the shell to expand wildcards in path/filenames.
php dot net at crazedsanity dot com
10.07.2009 17:29
For clarification, the "exitcode" is only valid the FIRST TIME IT IS CALLED after the process exits.

If you have a method that polls a spawned process for its status, you *MUST* have that same method capture the exitcode: if the method is called a second time (after realizing the pid is dead) and it hasn't cached that exitcode, it will receive the -1 mentioned.
lytithwyn at gmail dot com
29.12.2008 15:51
I have had lots of problems in the past bit trying to kill external commands run by proc_open.

Others have suggested using ps to find the children of the pid returned by proc_get_status, but on my system this doesn't work.  I'm using php-5.2.5 and apache-2.0.59 on linux kernel 2.6.21, and the processes I start with proc_open end up being owned by init (pid 1), not by the pid returned by proc_get_status.

I did notice, however, that the pid's of the processes were always above and very close to the proc_get_status pid.  Using that information, I wrote a little function that takes the name of a command, the starting pid at which to search (which would be the proc_get_status pid), and optionally a search limit as arguments.  It will use ps to list processes owned by apache (you may have to change this user name for your system), and search for the command specified.  The limit tells how far above the starting pid to search.  This will help if the command may have already exited, and you don't want to kill a process from a different session than the one you're working with.

Here's the code:

<?php
function findCommandPID($command, $startpid, $limit = 3)
{
   
$ps = `ps -u apache --sort=pid -o comm= -o pid=`;
   
$ps_lines = explode("\n", $ps);

   
$pattern = "/(\S{1,})(\s{1,})(\d{1,})/";

    foreach(
$ps_lines as $line)
    {
        if(
preg_match($pattern, $line, $matches))
        {
           
//this limits us to finding the command within $limit pid's of the parent;
            //eg, if ppid = 245, limit = 3, we won't search past 248
           
if($matches[3] > $startpid + $limit)
                break;

           
//try to match a ps line where the command matches our search
            //at a higher pid than our parent
           
if($matches[1] == $command && $matches[3] > $startpid)
                return
$matches[3];
        }
    }

    return
false;
}
?>
webmaster at rouen dot fr
9.07.2008 22:49
The following function takes an array of shell commands and executes them. It is able to execute up to $nb_max_process at the same time. As soon as one process is terminated, another one is executed. Quite useful if you want to batch process commands on a multi-processor or multi-core environment.

The example below tries to convert to PNG a list of SVG files submitted on the command line (using Inkscape).

(it's quick and dirty but works very well for me)

#!/usr/bin/php
<?php
function pool_execute($commandes,$nb_max_process) {
 
$pool=array();
  for(
$i=0;$i<$nb_max_process;$i++) {
   
$pool[$i]=FALSE;
  }

  while(
count($commandes)>0) {
   
$commande=array_shift($commandes);

   
$commande_lancee=FALSE;
    while(
$commande_lancee==FALSE) {
     
usleep(50000);

      for(
$i=0;$i<$nb_max_process and $commande_lancee==FALSE;$i++) {
        if(
$pool[$i]===FALSE) {
         
$pool[$i]=proc_open($commande,array(),$foo);
         
$commande_lancee=TRUE;
        } else {
         
$etat=proc_get_status($pool[$i]);
          if(
$etat['running']==FALSE) {
           
proc_close($pool[$i]);
           
$pool[$i]=proc_open($commande,array(),$foo);
           
$commande_lancee=TRUE;
          }
        }
      }
    }
  }
}

$fichiers=$argv;
array_shift($fichiers);
$commandes=array();
foreach(
$fichiers as $fichier) {
 
$entree=$fichier;
 
$sortie=basename($fichier,'.svg').".png";
 
$commandes[]='inkscape --file='.escapeshellarg($entree).' --export-area-canvas --export-png='.escapeshellarg($sortie);
}

pool_execute($commandes,4);
strrev xc.noxeh@ellij
5.06.2008 10:12
You can NOT rely on pid+1.
You could prefix exec to the command string, this will replace the /bin/sh script with the real thing you want to exec (use only if you don't do 'scary things' like pipes, output redirection, multiple commands, however if you know how they work, go ahead).
If you prefix exec, the /bin/sh process will only start your process, and the PID will be the same.
damien at cyg dot net
13.06.2007 15:06
Alternatively, if you're calling a subsequent php script using proc_open, you can have that process echo its own actual PID in the output.
Also, if you go through the /proc filesystem on linux, you can read through /proc/12345 where 12345 is the pid returned by proc_get_status (the pid of the /bin/sh instance) and it will list its child processes within.
andy dot shellam at mailnetwork dot co dot uk
5.04.2007 14:16
Further to my previous note, I've found out the PID returned is the PID of the shell (/bin/sh) that then runs the actual command requested.

I've raised this as bug #41003.
andy dot shellam at mailnetwork dot co dot uk
5.04.2007 13:58
To the poster above, same here on FreeBSD 6.1, PHP 5.2.1.

To get the correct PID to use for posix_kill I have to add 1 to the PID returned from proc_get_status.



PHP Powered Diese Seite bei php.net
The PHP manual text and comments are covered by the Creative Commons Attribution 3.0 License © the PHP Documentation Group - Impressum - mail("TO:Reinhard Neidl",...)