PHP Doku:: Schließt einen Prozess, der mit proc_open gestartet wurde und gibt den Exitcode dieses Prozesses zurück - function.proc-close.html

Verlauf / Chronik / History: (1) anzeigen

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

Ein Service von Reinhard Neidl - Webprogrammierung.

Funktionen zur Programmausführung

<<passthru

proc_get_status>>

proc_close

(PHP 4 >= 4.3.0, PHP 5)

proc_closeSchließt einen Prozess, der mit proc_open() gestartet wurde und gibt den Exitcode dieses Prozesses zurück

Beschreibung

int proc_close ( resource $process )

proc_close() entspricht pclose(), außer dass Die Funktion nur mit Prozessen arbeitet, die von proc_open() gestartet wurden. proc_close() wartet auf den zu beendenden Prozess und gibt seinen Exitcode zurück. Wenn Sie offene Pipes zu diesem Prozess haben, sollten Sie zuvor fclose() ausführen, um Deadlocks vorzubeugen - der Child-Prozess kann sich nicht beenden, solange noch Pipes geöffnet sind.

Parameter-Liste

process

Die zu schließende proc_open()-Ressource.

Rückgabewerte

Gibt den Termination-Status des gelaufenen Prozesses zurück.


8 BenutzerBeiträge:
- Beiträge aktualisieren...
simeonl at dbc dot co dot nz
3.11.2008 3:12
I have the same problem with a return code of -1 being returned because the --enable-sigchild flag is set as ashnazg at php dot net mentioned.  Unfortunely I'm told this is in the debian package, and we can't change the PHP install to fix this.

I've been able to work around this as follows, it adds an extra layer, which is not ideal, but in circumstances where you can't change the install it's better than nothing. 

I made a shell script as follows:

#!/bin/bash
eval $1
echo $? 1>&3

Basically that executes the argument of the script and echos the return code to pipe 3.  I defined pipe 3 in descriptorspec for passing the return status back to PHP, doing an end run around this "will not fix" situation.

Naturally this is no use on a windows system, but perhaps the windows package isn't compiled with the --enable-sigchild flag set?
proc_close_at_php_net at mailfilter dot com dot ar
10.06.2008 14:51
In response to the problem mentioned by ashnazg at php dot net about --enable-sigchild masking the real exit status, this is how I tricked it (Linux):

$descriptorspec = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w"));
$cmd = "dosomethingatshell";
// My hack:
$cmd = "( $cmd ) 3>/dev/null ; echo \$? >&3";
$descriptorspec[3] = array("pipe","w");
// .... execute ....
$res = proc_open($cmd, $descriptorspec, $pipes);
if( is_resource($res) )
{
    .....
    // Get the exit status for the original command
    $status = (int) str_replace("\n","",stream_get_contents($pipes[3]));
    foreach($pipes as $pipe) fclose($pipe);
    $n = proc_close($res);
    // $n is not useful; $status has the actual exit status
    // Notice that $status is not the termination status,
    // as proc_close() should return but only the *exit* status
}
morrisdavidd at gmail dot com
5.06.2008 1:41
Consider the following pseudo code:

$SOME_PROCESS = proc_open(/* something here */);
...
$status = proc_get_status($SOME_PROCESS);
...
$exitCode = proc_close($SOME_PROCESS);

If the external program has exited on its own before the call to proc_get_status, then $exitCode == -1

So consider using:
$actualExitCode = ($status["running"] ? $exitCode : $status["exitcode"] );
noname at bspamfree dot org
2.04.2008 22:44
According to the discussion associated with bug #17538, the "termination status" as returned by this function is not the same thing as the exit code ($? in BASH). To extract the exit code from the termination status, something like this is needed:

$exitcode = (proc_close($proc) >> 8) & 0xff;
ashnazg at php dot net
5.10.2007 23:25
It seems that if you configured --enable-sigchild when you compiled PHP (which from my reading is required for you to use Oracle stuff), then return codes from proc_close() cannot be trusted.

Using proc_open's Example 1998's code on versions I have of PHP4 (4.4.7) and PHP5 (5.2.4), the return code is always "-1".  This is also the only return code I can cause by running other shell commands whether they succeed or fail.

I don't see this caveat mentioned anywhere except on this old bug report -- http://bugs.php.net/bug.php?id=29123
e-t172 at e-t172 dot net
18.10.2005 19:59
Just an improvement of my precedent function :

<?php
function proc_close_nobug($proc)
{
   
$status = proc_get_status($proc);
   
exec('kill '.$status['pid'].' 2>/dev/null >&- >/dev/null');
   
proc_close($proc);
}
?>

In fact, proc_close() works when called after "kill". This is useful because it doesn't generate "defunct processes" as the precedent version.
oohay251 at yahoo dot com
15.09.2005 16:06
From various Internet posts and recent experience, I have observed that you cannot rely on proc_close returning the accurate return code of the child process. The return code also depends on wether or not you read from the stdout/stderr pipes, as my example shows. I work around this by writing the exit code to an additional file descriptor.

<?
$descriptorspec
= array(
      
0 => array('pipe', 'r'),  // stdin is a pipe that the child will read from
      
1 => array('pipe', 'w'),  // stdout is a pipe that the child will write to
      
2 => array('pipe', 'w'), // stderr is a pipe that the child will write to
   
);
   
$proc = @proc_open("/bin/ls -l /etc/passwd", $descriptorspec, $pipes);
   
fclose($pipes[0]);
   
$output = array();
    while (!
feof($pipes[1])) array_push($output, rtrim(fgets($pipes[1],1024),"\n"));
   
fclose($pipes[1]);
    while (!
feof($pipes[2])) array_push($output, rtrim(fgets($pipes[2],1024),"\n"));
   
fclose($pipes[2]);
   
$exit=proc_close($proc);
   
print_r($output);
    echo
"exitcode $exit\n\n";

$descriptorspec = array(
      
0 => array('pipe', 'r'),  // stdin is a pipe that the child will read from
      
1 => array('pipe', 'w'),  // stdout is a pipe that the child will write to
      
2 => array('pipe', 'w'), // stderr is a pipe that the child will write to
   
);
   
$proc = @proc_open("/bin/ls -l /etc/passwd", $descriptorspec, $pipes);
   
fclose($pipes[0]);
   
fclose($pipes[1]);
   
fclose($pipes[2]);
   
$exit=proc_close($proc);
    echo
"exitcode $exit\n\n";

$descriptorspec = array(
      
0 => array('pipe', 'r'),  // stdin is a pipe that the child will read from
      
1 => array('pipe', 'w'),  // stdout is a pipe that the child will write to
      
2 => array('pipe', 'w'), // stderr is a pipe that the child will write to
      
3 => array('pipe', 'w'), // stderr is a pipe that the child will write to
   
);
   
$proc = @proc_open("/bin/ls -l /etc/passwd;echo $? >&3", $descriptorspec, $pipes);
   
fclose($pipes[0]);
   
$output = array();
   
//comment next line to get correct exicode
   
while (!feof($pipes[1])) array_push($output, rtrim(fgets($pipes[1],1024),"\n"));
   
fclose($pipes[1]);
    while (!
feof($pipes[2])) array_push($output, rtrim(fgets($pipes[2],1024),"\n"));
   
fclose($pipes[2]);
    if (!
feof($pipes[3])) $output['exitcode']=rtrim(fgets($pipes[3],5),"\n");
   
fclose($pipes[3]);
   
proc_close($proc);
   
print_r($output);
?>

Outputs on my system:

Array
(
    [0] => -rw-r--r--  1 root root 1460 2005-09-02 09:52 /etc/passwd
    [1] =>
    [2] =>
)
exitcode -1

exitcode 1

Array
(
    [0] => -rw-r--r--  1 root root 1460 2005-09-02 09:52 /etc/passwd
    [1] =>
    [2] =>
    [exitcode] => 0
)
sergey1369 at narod dot ru
29.08.2003 12:16
Under PHP/4.3.3RC2, in case of two processes
these function may hangs. Work around is not use
proc_close, or put it after all fcloses done.

For example, this code hangs.

$ph1 = proc_open("cat",
 array(0=>array("pipe","r"),1=>array("pipe","w")),
 $pipes1);
$ph2 = proc_open("cat",
 array(0=>array("pipe","r"),1=>array("pipe","w")),
 $pipes2);

fclose($pipes1[0]); fclose($pipes1[1]); proc_close($ph1);
fclose($pipes2[0]); fclose($pipes2[1]); proc_close($ph2);

This code worked for me:

$ph1 = proc_open("cat",
 array(0=>array("pipe","r"),1=>array("pipe","w")),
 $pipes1);
$ph2 = proc_open("cat",
 array(0=>array("pipe","r"),1=>array("pipe","w")),
 $pipes2);

fclose($pipes1[0]); fclose($pipes1[1]);
fclose($pipes2[0]); fclose($pipes2[1]);
proc_close($ph1); proc_close($ph2);



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",...)