2010-02-23 42 views
43

Trong PHP tôi đang thực hiện một lệnh với lệnh exec() và nó trả về nếu thành công một URL;PHP StdErr sau Exec()

$url = exec('report'); 

Tuy nhiên, tôi muốn kiểm tra tiêu chuẩn, nếu có sự cố. Tôi sẽ đọc luồng như thế nào? Tôi muốn sử dụng php: // stderr, nhưng tôi không chắc chắn làm thế nào để sử dụng nó.

+0

Tôi sẽ khuyên bạn nên sử dụng thành phần Symfony/Process. –

Trả lời

65

Nếu bạn muốn thực thi lệnh và nhận cả hai stderrstdout, không được "hợp nhất", giải pháp có thể sử dụng proc_open, cung cấp mức kiểm soát tuyệt vời đối với lệnh đang được thực hiện - bao gồm cả cách đến đường ống stdin/stdout/stderr.


Và đây là một ví dụ: chúng ta hãy xem xét chúng tôi có điều này vỏ kịch bản, trong test.sh, mà viết cho cả stderrstdout:

#!/bin/bash 

echo 'this is on stdout'; 
echo 'this is on stdout too'; 

echo 'this is on stderr' >&2; 
echo 'this is on stderr too' >&2; 


Bây giờ, chúng ta hãy đang một số PHP, trong temp.php - trước tiên, chúng tôi khởi tạo trình mô tả i/o:

$descriptorspec = array(
    0 => array("pipe", "r"), // stdin 
    1 => array("pipe", "w"), // stdout 
    2 => array("pipe", "w"), // stderr 
); 


Và, sau đó, thực hiện lệnh test.sh, sử dụng những mô tả, trong thư mục hiện hành, và nói i/o nên từ/đến $pipes:

$process = proc_open('./test.sh', $descriptorspec, $pipes, dirname(__FILE__), null); 


Bây giờ chúng ta có thể đọc từ hai ống đầu ra :

$stdout = stream_get_contents($pipes[1]); 
fclose($pipes[1]); 

$stderr = stream_get_contents($pipes[2]); 
fclose($pipes[2]); 


Và, nếu chúng ta sản lượng nội dung của hai biến:

echo "stdout : \n"; 
var_dump($stdout); 

echo "stderr :\n"; 
var_dump($stderr); 


Chúng tôi nhận được đầu ra sau khi thực hiện kịch bản temp.php:

$ php ./temp.php 
stdout : 
string(40) "this is on stdout 
this is on stdout too 
" 
stderr : 
string(40) "this is on stderr 
this is on stderr too 
" 


Hope this helps :-)

+3

Khi sử dụng điều này, hãy chắc chắn rằng tất cả các bạn sử dụng proc_close khi bạn đang làm tất cả vì lợi ích sạch sẽ. –

+0

Tại sao bạn chuyển hướng dẫn đến một quá trình var? –

+3

@BriceFavre Ông đặt nó trong một quá trình var để ông có thể đóng nó sau này với proc_close, mà cũng sẽ trả về mã trả về quá trình đã thoát. '$ returnCode = proc_close ($ process);' –

6

Một cách khác để có được Đã hủy stdout/stderr.

$pp_name = "/tmp/pp_test"; 
@unlink($pp_name); 
posix_mkfifo($pp_name, 0777); 
$pp = fopen($pp_name, "r+"); 
stream_set_blocking($pp, FALSE); 
exec("wget -O - http://www.youtube.com 2>$pp_name", $r_stdout); 
$r_stderr = stream_get_contents($pp); 
var_dump($r_stderr); 
fclose($pp); 
unlink($pp_name); 

Nếu bạn muốn bỏ qua stdout và nhận được chỉ stderr, bạn có thể thử này:

exec("wget -O - http://www.youtube.com 2>&1 >/dev/null", $r_stderr); 
30

Một chức năng nhỏ mà có thể hữu ích:

function my_shell_exec($cmd, &$stdout=null, &$stderr=null) { 
    $proc = proc_open($cmd,[ 
     1 => ['pipe','w'], 
     2 => ['pipe','w'], 
    ],$pipes); 
    $stdout = stream_get_contents($pipes[1]); 
    fclose($pipes[1]); 
    $stderr = stream_get_contents($pipes[2]); 
    fclose($pipes[2]); 
    return proc_close($proc); 
} 

Mã thoát được trả lại và STDOUT và STDERR là các tham số tham chiếu nếu bạn cần chúng.

+2

Đẹp và đơn giản, hoạt động hoàn hảo. Cảm ơn vì đăng!!! –

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