2012-02-27 30 views
6

Trong php có một số phương pháp để thực thi một lệnh shell:Thực thi chương trình trong php - hiển thị và trở đầu ra

  • hệ thống()
  • passthru()
  • shell_exec()
  • exec ()

Đầu tiên hiển thị hai đầu ra nhưng không trả lại. Kết quả trả về hai lần cuối nhưng không hiển thị.

Tôi muốn chạy lệnh shell yêu cầu nhiều thời gian nhưng nó hiển thị một số đầu ra vì vậy tôi biết nó không treo. Tuy nhiên vào cuối tôi muốn xử lý đầu ra này trong php. Nếu tôi chọn một trong hai đầu tiên tôi sẽ không nhận được đầu ra vì vậy tôi sẽ không thể xử lý nó trong php. Nếu tôi chạy một trong hai cuối cùng tôi sẽ có thể xử lý đầu ra tuy nhiên chương trình của tôi sẽ treo thời gian rất dài mà không xuất ra bất cứ điều gì.

Có cách nào để chạy lệnh trình bao sẽ hiển thị đầu ra ngay lập tức và trả lại không?

+0

Liệu các đối số thứ hai vào hệ thống() gọi không giúp được gì? – KTastrophy

+0

Đối số thứ hai là trạng thái trả về của lệnh được thực hiện, ví dụ: 0 nếu mọi thứ đều ổn và 1 nếu có lỗi. Tôi nên đề cập đến tôi cần điều này quá - shell_exec() là một trong đó không hỗ trợ đó. –

+0

Tôi không nghĩ rằng có bất kỳ lệnh PHP nào sẽ thực thi mã shell và đầu ra in ra màn hình trước khi thực hiện xong. – Travesty3

Trả lời

2

Có lẽ điều này sẽ khiến bạn quan tâm? proc_open() - http://www.php.net/manual/en/function.proc-open.php

Và đây là một đoạn tiện dụng mà có thể làm việc cho bạn (nó sao chép từ các ý kiến ​​trên trang web tôi đã cho bạn những liên kết đến):

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

Cảm ơn! Không có cách nào tôi có thể suy ra làm thế nào để có được mã trạng thái trả về :) –

+0

Không vấn đề gì, Kamil. :) – Pateman

2

lẽ bạn có thể sử dụng popen(), mà thực hiện một chương trình và đọc kết quả của mình thông qua một tập tin xử lý, như vậy:

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

Cảm ơn! Điều này sẽ làm việc tuy nhiên tôi quên đề cập đến tôi cần cũng trở lại tình trạng của lệnh thực hiện vì vậy có lẽ proc_open (tương tự) sẽ cho phép tôi làm điều đó - cảm ơn anyway! –

+0

Bạn được chào đón. Vui vì bạn đã giải quyết nó! – elias

Các vấn đề liên quan