Hướng dẫn dùng passthru trong PHP

Như được rút ra từ http://php.net/ && Chipmunkninja :

Các hệ thống () Chức năng

Hàm hệ thống trong PHP lấy một đối số chuỗi với lệnh để thực thi cũng như bất kỳ đối số nào bạn muốn truyền cho lệnh đó. Hàm này thực thi lệnh được chỉ định và đưa bất kỳ văn bản kết quả nào vào luồng đầu ra (có thể là đầu ra HTTP trong tình huống máy chủ web hoặc bàn điều khiển nếu bạn đang chạy PHP dưới dạng công cụ dòng lệnh). Sự trở lại của chức năng này là dòng đầu ra cuối cùng từ chương trình, nếu nó phát ra đầu ra văn bản.

Các exec () Chức năng

Chức năng hệ thống khá hữu ích và mạnh mẽ, nhưng một trong những vấn đề lớn nhất với nó là tất cả văn bản kết quả từ chương trình đi trực tiếp vào luồng đầu ra. Sẽ có những tình huống mà bạn có thể muốn định dạng văn bản kết quả và hiển thị nó theo một cách khác hoặc hoàn toàn không hiển thị nó.

Đối với điều này, hàm exec trong PHP hoàn toàn thích nghi. Thay vì tự động kết xuất tất cả văn bản được tạo bởi chương trình đang được thực thi vào luồng đầu ra, nó cho bạn cơ hội để đưa văn bản này vào một mảng được trả về trong tham số thứ hai cho hàm:

Các shell_exec () Chức năng

Hầu hết các chương trình chúng tôi đã thực hiện cho đến nay, ít nhiều, là các chương trình thực tế1. Tuy nhiên, môi trường mà người dùng Windows và Unix hoạt động thực sự phong phú hơn nhiều so với điều này. Người dùng Windows có tùy chọn sử dụng chương trình Windows Command Prompt, cmd.exe Chương trình này được gọi là shell lệnh.

Các passthru () Chức năng

Một hàm hấp dẫn mà PHP cung cấp tương tự như các hàm mà chúng ta đã thấy cho đến nay là hàm passthru. Hàm này, giống như các hàm khác, thực thi chương trình mà bạn nói với nó. Tuy nhiên, sau đó nó tiến hành gửi ngay đầu ra thô từ chương trình này đến luồng đầu ra mà PHP hiện đang hoạt động (tức là HTTP trong kịch bản máy chủ web hoặc shell trong phiên bản dòng lệnh của PHP).

Các proc_open () Chức năng và popen () chức năng

Proc_open () tương tự như popen () nhưng cung cấp mức độ kiểm soát lớn hơn nhiều đối với việc thực hiện chương trình. cmd là lệnh được thực thi bởi shell. descriptorspec là một mảng được lập chỉ mục trong đó khóa đại diện cho số mô tả và giá trị đại diện cho cách PHP sẽ chuyển mô tả đó cho tiến trình con. các đường ống sẽ được đặt thành một mảng các con trỏ tệp được lập chỉ mục tương ứng với phần cuối của bất kỳ đường ống nào được tạo. Giá trị trả về là một tài nguyên đại diện cho quá trình; bạn nên giải phóng nó bằng cách sử dụng Proc_close () khi bạn kết thúc với nó.

112 hữu ích 5 bình luận chia sẻ

(PHP 4, PHP 5, PHP 7, PHP 8)

passthruExecute an external program and display raw output

Description

passthru(string $command, int &$result_code = null): ?false

Parameters

command

The command that will be executed.

result_code

If the result_code argument is present, the return status of the Unix command will be placed here.

Return Values

Returns null on success or false on failure.

Errors/Exceptions

Will emit an E_WARNING if passthru() is unable to execute the command.

Throws a ValueError if command is empty or contains null bytes.

Changelog

VersionDescription
8.0.0 If command is empty or contains null bytes, passthru() now throws a ValueError. Previously it emitted an E_WARNING and returned false.

Notes

Warning

When allowing user-supplied data to be passed to this function, use escapeshellarg() or escapeshellcmd() to ensure that users cannot trick the system into executing arbitrary commands.

Note:

If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.

See Also

  • exec() - Execute an external program
  • system() - Execute an external program and display the output
  • popen() - Opens process file pointer
  • escapeshellcmd() - Escape shell metacharacters
  • backtick operator

puppy at cyberpuppy dot org

17 years ago

Regarding swbrown's comment...you need to use an output buffer if you don't want the data displayed.

For example:
ob_start();
passthru("<i>command</i>");
$var = ob_get_contents();
ob_end_clean(); //Use this instead of ob_flush()

This gets all the output from the command, and exits without sending any data to stdout.

jo at durchholz dot org

14 years ago

Note to Paul Giblock: the command *is* run through the shell.
You can verify this on any Linux system with

<?php
passthru
('echo $PATH');
?>

You'll get the content of the PATH environment variable, not the string $PATH.

igor at bboy dot ru

17 years ago

If you are using passthru() to download files (for dynamically generated content or something outside webserver root) using similar code:

header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"myfile.zip\"");
header("Content-Length: 11111");
passthru("cat myfile.zip",$err);

and your download goes fine, but subsequent downloads / link clicks are screwed up, with headers and binary data being all over the website, try putting

exit();

after the passthrough. This will exit the script after the download is done and will not interfere with any future actions.

sarel dot w at envent dot co dot za

17 years ago

Zak Estrada
14-Dec-2004 11:21
Remember to use the full path (IE '/usr/local/bin/foo' instead of 'foo') when using passthru, otherwise you'll get an exit code of 127 (command not found).

Remember, you'll also get this error if your file does not have executable permission.

myselfasunder at gmail dot com dot dfvuks

11 years ago

PHP's program-execution commands fail miserably when it comes to STDERR, and the proc_open() command doesn't work all that consistently in non-blocking mode under Windows.

This command, although useful, is no different. To form a mechanism that will see/capture both STDOUT and STDERR output, pipe the command to the 'tee' command (which can be found for Windows), and wrap the whole thing in output buffering.

Dustin Oprea

Zak Estrada

17 years ago

Remember to use the full path (IE '/usr/local/bin/foo' instead of 'foo') when using passthru, otherwise you'll get an exit code of 127 (command not found).

mail at dtrasbo dot dk

1 month ago

To capture the output of a command in a string without using output buffer functions, use shell_exec()

Chroot

14 years ago

If you have chrooted apache and php, you will also want to put /bin/sh into the chrooted environment. Otherwise, the exec() or passthru() will not function properly, and will produce error code 127, file not found.

divinity76+spam at gmail dot com

1 month ago

if you have problems with passthru("docker-compose ...bash") losing interactive shell size information, try using proc_open instead, for some reason docker-compose bash knows the size of the outer terminal when i use use proc_open, but loses that information when i use passthru,

eg i replaced
<?php
passthru
("docker-compose -f docker-compose.yml bash",$ret);
?>
with
<?php
$empty1
=array();
$empty2=array();
$proc=proc_open("docker-compose -f docker-compose.yml bash",$empty1,$empty2 );
$ret = proc_close($proc);
?>

and suddenly docker-compose bash knew my terminal size :)

tox at novasonica dot com

3 years ago

I was trying to implement a system that allows running arbitrary CLI commands with parameters, but I kept running into the issues with user prompts from the command as they would let execution hang. The solution is simple: just use passthru() as it outputs everything and correctly handles user prompts out of the box.

Stuart Eve

16 years ago

I dunno if anyone else might find this useful, but when I was trying to use the passthru() command on Suse9.3 I was having no success with the command:

$command = 'gdal_translate blahahahaha';

passthru($command);

It only worked once I put:

$command = '/usr/bin/local/gdal_translate blalalala';

passthru($command);

stuartc1 at NOSPAM dot hotmail dot com

17 years ago

Thought it might beuseful to note the passthru seems to supress error messages whilst being run in Dos on Windows (test on NT).

To show FULL raw output including errors, use system().

swbrown at ucsd dot edu

19 years ago

passthru() seems absolutely determined to buffer output no matter what you do, even with ob_implicit_flush().  The solution seems to be to use popen() instead.

kpierre at fit dot edu

20 years ago

The documention does not mention that passthru() will only display standard output and not standard error.

If you are running a script you can pipe the STDERR to STDOUT by doing

exec 2>&1

Eg. the script below will actually print something with the passthru() function...

#!/bin/sh
exec 2>&1
ulimit -t 60
cat nosuchfile.txt

nuker at list dot ru

16 years ago

I wrote function, that gets proxy server value from the Internet Explorer (from
registry). It was tested in Windows XP Pro

(Sorry for my English)

<?php
function getProxyFromIE()
{
       
exec("reg query \"HKEY_CURRENT_USER\Software\Microsoft".
       
"\Windows\CurrentVersion\Internet Settings\" /v ProxyEnable",
       
$proxyenable,$proxyenable_status);exec("reg query \"HKEY_CURRENT_USER\Software\Microsoft".
       
"\Windows\CurrentVersion\Internet Settings\" /v ProxyServer",
       
$proxyserver);

        if(

$proxyenable_status!=0)
        return
false; #Can't access the registry! Very very bad...
       
else
        {
       
$enabled=substr($proxyenable[4],-1,1);
        if(
$enabled==0)
        return
false;
        else
        {
       
$proxy=ereg_replace("^[ \t]{1,10}ProxyServer\tREG_SZ[ \t]{1,20}","",
       
$proxyserver[4]);

        if(

ereg("[\=\;]",$proxy))
        {
            
$proxy=explode(";",$proxy);
             foreach(
$proxy as $i => $v)
             {
                   if(
ereg("http",$v))
                   {
                  
$proxy=str_replace("http=","",$v);
                   break;
                   }
             }
             if(@!
ereg("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\:".
            
"[0-9]{1,5}$",$proxy))
             return
false;
             else
             return
$proxy;
        }
        else
        return
$proxy;
        }

        }
}

?>
Note, that this function returns FALSE if proxy is disabled in Internet
Explorer. This function returns ONLY HTTP proxy server.

Usage:
<?php
$proxy
=getProxyFromIE();
if(!
$proxy)
echo
"Can't get proxy!";
else
echo
$proxy;
?>

vijayramanan at rediffmail dot com

17 years ago

I had an issue when i used exec

I think we were echoing information on the test.php script.
for eg: when we tried

exec(php test.php,$array,$error);

the return was 127 and the code was failing.

checking the note on this page gave us a hint to use passthru instead.
The only thing to note is that you need to provide the fuull path.

now our command became

passthru(/bin/php /pathtotest/test.php,$array,$error);

this works.

yipeee!!!!!

Paul Giblock

15 years ago

Stuart:

The pasthru function does not execute the program through the shell.  What this mean, among other things, is that your PATH variable is never set.  Therefore, you have to use full paths on everything.

I believe system() will run your program underneith a shell.  This allow the program to run in a 'normal' environment.

-Paul

sidney at jigsaw dot nl

21 years ago

PJ's ulimit example is nice; however, if you include multiple commands in the script after the ulimit command, each gets its own, seperate 60 second time slot!<br>

Furthermore, these sixty seconds are *CPU* time. Most programs hang for other reasons than CPU hogging (for example, waiting for a database connection) so for most purposes the number 60 is rather too high.<br>

Try "ulimit -t 1" first, which will give you about 10^9 cycles on modern hardware -- quite enough to get a lot of work done!

PJ at piggei dot com

21 years ago

About the problem of zombies, you may call a bash script like this:

--------------------------
#! /bin/bash
ulimit -t 60

<your command here>
--------------------------

me at yourMomsPussy dot cum

5 years ago

`command` // back ticks drop you out of PHP mode into shell
exec('command', $output); // exec will allow you to capture the return of a command as reference
shell_exec('command'); // will return the output to a variable
system(); //as seen above.

php @ richud dot com

18 years ago

Regarding kpierre's post, be mindful that if you shell script errors, you will find the error output from it in the base error_log file (not virtualhost error_log) in apache.

jcr at marvel-databadge dot com

19 years ago

With apache 2.x on RH9 passthru() writes 1 byte at a time. Apache 2.x buffers and chunk encodes the output for you - but the chunked encoding devides the output in chunks of 1 byte each...thus several bytes of overhead per byte. I guess that buffering behaviour is by design - but caused problems for me with IE adobe acrobot 5 plugin. The plugin doesn't like like it if you send it a stream of 1 byte chunks - it tells you your file is not a pdf or gives a blank screen. Using output buffering (ob_start / ob_endflush) gives reasonable size chunks and the plugin works OK.