2012-02-27 10 views
6

en PHP hay varios métodos para ejecutar un comando shell:programa en ejecución en php - pantalla y volver salida

  • sistema()
  • passthru()
  • shell_exec()
  • exec ()

Las dos primeras pantallas se imprimen pero no la devuelven. Las dos últimas devuelven la salida pero no la muestran.

Quiero ejecutar el comando de shell que requiere mucho tiempo pero muestra algunos resultados, así que sé que no se cuelga. Sin embargo, al final quiero procesar esta salida en php. Si elijo uno de los dos primeros, no obtendré ningún resultado, por lo que no podré procesarlo en php. Si ejecuto uno de los dos últimos, podré procesar el resultado; sin embargo, mi programa se bloqueará durante mucho tiempo sin generar ningún resultado.

¿Hay alguna forma de ejecutar un comando de shell que muestre la salida inmediatamente y la devuelva?

+0

¿El segundo argumento al sistema() llamar no ayuda? – KTastrophy

+0

El segundo argumento es el estado de retorno del comando ejecutado, p. 0 si todo estaba bien y 1 si hubo error. Debo mencionar que también necesito esto: shell_exec() es el que no admite eso. –

+0

No creo que haya ningún comando PHP que ejecute el código del shell e imprima el resultado en la pantalla antes de que la ejecución finalice. – Travesty3

Respuesta

2

Tal vez éste le va a interesar? proc_open() - http://www.php.net/manual/en/function.proc-open.php

Y aquí es un fragmento útil que podría funcionar para usted (se copian de los comentarios en el sitio que le di el enlace a):

<?php 
/* 
* Execute and display the output in real time (stdout + stderr). 
* 
* Please note this snippet is prepended with an appropriate shebang for the 
* CLI. You can re-use only the function. 
* 
* Usage example: 
* chmod u+x proc_open.php 
* ./proc_open.php "ping -c 5 google.fr"; echo RetVal=$? 
*/ 
define(BUF_SIZ, 1024);  # max buffer size 
define(FD_WRITE, 0);  # stdin 
define(FD_READ, 1);  # stdout 
define(FD_ERR, 2);  # stderr 

/* 
* Wrapper for proc_*() functions. 
* The first parameter $cmd is the command line to execute. 
* Return the exit code of the process. 
*/ 
function proc_exec($cmd) 
{ 
    $descriptorspec = array(
     0 => array("pipe", "r"), 
     1 => array("pipe", "w"), 
     2 => array("pipe", "w") 
    ); 

    $ptr = proc_open($cmd, $descriptorspec, $pipes, NULL, $_ENV); 
    if (!is_resource($ptr)) 
     return false; 

    while (($buffer = fgets($pipes[FD_READ], BUF_SIZ)) != NULL 
      || ($errbuf = fgets($pipes[FD_ERR], BUF_SIZ)) != NULL) { 
     if (!isset($flag)) { 
      $pstatus = proc_get_status($ptr); 
      $first_exitcode = $pstatus["exitcode"]; 
      $flag = true; 
     } 
     if (strlen($buffer)) 
      echo $buffer; 
     if (strlen($errbuf)) 
      echo "ERR: " . $errbuf; 
    } 

    foreach ($pipes as $pipe) 
     fclose($pipe); 

    /* Get the expected *exit* code to return the value */ 
    $pstatus = proc_get_status($ptr); 
    if (!strlen($pstatus["exitcode"]) || $pstatus["running"]) { 
     /* we can trust the retval of proc_close() */ 
     if ($pstatus["running"]) 
      proc_terminate($ptr); 
     $ret = proc_close($ptr); 
    } else { 
     if ((($first_exitcode + 256) % 256) == 255 
       && (($pstatus["exitcode"] + 256) % 256) != 255) 
      $ret = $pstatus["exitcode"]; 
     elseif (!strlen($first_exitcode)) 
      $ret = $pstatus["exitcode"]; 
     elseif ((($first_exitcode + 256) % 256) != 255) 
      $ret = $first_exitcode; 
     else 
      $ret = 0; /* we "deduce" an EXIT_SUCCESS ;) */ 
     proc_close($ptr); 
    } 

    return ($ret + 256) % 256; 
} 

/* __init__ */ 
if (isset($argv) && count($argv) > 1 && !empty($argv[1])) { 
    if (($ret = proc_exec($argv[1])) === false) 
     die("Error: not enough FD or out of memory.\n"); 
    elseif ($ret == 127) 
     die("Command not found (returned by sh).\n"); 
    else 
     exit($ret); 
} 
?> 
+0

Gracias! No hay manera de que yo pueda deducir cómo obtener el código de estado de retorno :) –

+0

No hay problema, Kamil. :) – Pateman

2

Tal vez se puede utilizar popen(), que ejecuta un programa y lee su salida a través de un archivo de manejar, así:

$handle = popen('/bin/ls', 'r'); 
while ($line = fread($handle, 100)){ 
    echo $line; 
} 
pclose($handle); 
+0

Gracias! Esto funcionará, sin embargo, olvidé mencionar que también necesito devolver el estado del comando ejecutado, por lo que probablemente proc_open (que sea similar) me permita hacerlo, ¡gracias de todos modos! –

+0

De nada. ¡Me alegra que lo hayas resuelto! – elias

Cuestiones relacionadas