2012-02-27 15 views
6

In php ci sono diversi metodi per eseguire un comando shell:programma in esecuzione in php - display e tornare uscita

  • sistema()
  • passante()
  • shell_exec()
  • exec (

I primi due display emettono ma non lo restituiscono. Gli ultimi due restituiscono l'output ma non lo visualizza.

Voglio eseguire il comando di shell che richiede molto tempo ma visualizza un po 'di output, quindi so che non si blocca. Comunque alla fine voglio elaborare questo output in php. Se scelgo uno dei primi due non otterrò l'output quindi non potrò elaborarlo in php. Se eseguo uno degli ultimi due, sarò in grado di elaborare l'output, tuttavia il mio programma si bloccherà per molto tempo senza emettere alcunché.

C'è un modo per eseguire un comando shell che visualizzerà immediatamente l'output e lo restituirà?

+0

fa il secondo argomento al sistema() non chiamare aiuto? – KTastrophy

+0

Il secondo argomento è lo stato di ritorno del comando eseguito ad es. 0 se tutto è andato bene e 1 se c'è stato errore. Dovrei menzionare che ho bisogno anche di questo - shell_exec() è quello che non lo supporta. –

+0

Non penso ci sia alcun comando PHP che eseguirà il codice shell e stamperà l'output sullo schermo prima che l'esecuzione sia terminata. – Travesty3

risposta

2

Forse questo uno sarà interessarvi? proc_open() - http://www.php.net/manual/en/function.proc-open.php

Ed ecco un frammento di pratico che potrebbe funzionare per voi (è copiato dai commenti sul sito che ti ho dato il link al):

<?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

Grazie! Non c'è modo che io possa mai dedurre come ottenere il codice di stato di ritorno :) –

+0

Nessun problema, Kamil. :) – Pateman

2

Forse è possibile utilizzare popen(), che esegue un programma e legge la sua uscita attraverso un file-handle, in questo modo:

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

Grazie! Funzionerà comunque, ma ho dimenticato di menzionare che ho bisogno anche di restituire lo status del comando eseguito, quindi probabilmente proc_open (che è simile) mi permetterà di farlo - grazie comunque! –

+0

Prego. Sono contento che l'hai risolto! – elias