2012-02-27 4 views
6

В PHP существует несколько методов, чтобы выполнить команду оболочки:Выполнение программы в PHP - дисплея и возврата вывода

  • системы()
  • PassThru()
  • shell_exec()
  • EXEC ()

Первые два дисплея выводятся, но не возвращают его. Последние два вывода выводятся, но не отображают его.

Я хочу запустить команду оболочки, для которой требуется много времени, но она отображает некоторый вывод, поэтому я знаю, что он не зависает. Однако в конце я хочу обработать этот вывод в php. Если я выберу одно из первых двух, я не получу выход, поэтому я не смогу обработать его в php. Если я запустил один из двух последних, я смогу обработать выходные данные, но моя программа будет висеть очень долго, не выводя ничего.

Есть ли способ запустить команду оболочки, которая немедленно отобразит вывод и вернет его?

+0

ли второй аргумент системы() позвонить не поможет? – KTastrophy

+0

Второй аргумент - это статус возврата выполненной команды, например. 0, если все было нормально и 1, если была ошибка. Я должен упомянуть, что мне тоже нужно - shell_exec() - тот, который этого не поддерживает. –

+0

Я не думаю, что есть какая-либо команда PHP, которая будет выполнять код оболочки и выводить вывод на экран перед завершением выполнения. – Travesty3

ответ

2

Может быть, это один вас заинтересует? proc_open() - http://www.php.net/manual/en/function.proc-open.php

А вот удобный фрагмент кода, который может работать для вас (это копируется из комментариев на сайте я дал вам ссылку на):

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

Спасибо! Нет никакого способа, я бы когда-либо вывести, как получить код статуса возврата :) –

+0

Нет проблем, Камил. :) – Pateman

2

Может быть, вы можете использовать popen(), который выполняет программу и считывает ее вывод через файл-ручки, например, так:

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

Спасибо! Это будет работать, однако я забыл упомянуть, что мне нужно также вернуть статус выполненной команды, поэтому, вероятно, proc_open (что похоже) позволит мне это сделать - спасибо в любом случае! –

+0

Добро пожаловать. Рад, что вы это решили! – elias

Смежные вопросы