PHP Conference Japan 2024

passthru

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

passthru执行外部程序并显示原始输出

描述

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

passthru() 函数类似于 exec() 函数,它执行 command。当 Unix 命令的输出是需要直接传递回浏览器的二进制数据时,应该使用此函数来代替 exec()system()。一个常见的用途是执行诸如 pbmplus 实用程序之类的程序,这些程序可以直接输出图像流。通过将 Content-type 设置为 image/gif,然后调用 pbmplus 程序输出 gif,您可以创建直接输出图像的 PHP 脚本。

参数

command

将要执行的命令。

result_code

如果存在 result_code 参数,则 Unix 命令的返回状态将放置在此处。

返回值

成功时返回 null,失败时返回 false

错误/异常

如果 passthru() 无法执行 command,将发出 E_WARNING

如果 command 为空或包含空字节,则抛出 ValueError

变更日志

版本 描述
8.0.0 如果 command 为空或包含空字节,passthru() 现在会抛出 ValueError。以前它会发出 E_WARNING 并返回 false

备注

警告

当允许将用户提供的数据传递到此函数时,请使用 escapeshellarg()escapeshellcmd() 来确保用户无法欺骗系统执行任意命令。

注意:

如果使用此函数启动程序,为了使其能够在后台继续运行,必须将程序的输出重定向到文件或其他输出流。否则,PHP 将挂起,直到程序执行结束。

参见

添加注释

用户贡献的注释 15 条注释

cyberpuppy dot org 的 puppy
19 年前
关于 swbrown 的评论……如果您不希望显示数据,则需要使用输出缓冲。

例如
ob_start();
passthru("<i>command</i>");
$var = ob_get_contents();
ob_end_clean(); // 使用此方法代替 ob_flush()

这将获取命令的所有输出,并在不向 stdout 发送任何数据的情况下退出。
durchholz dot org 的 jo
17 年前
致 Paul Giblock 的说明:命令确实通过 shell 运行。
您可以在任何 Linux 系统上使用以下命令进行验证:

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

您将获得 PATH 环境变量的内容,而不是字符串 $PATH。
gmail dot com 的 divinity76+spam
2 年前
如果您在使用 passthru("docker-compose ...bash") 时遇到丢失交互式 shell 大小信息的问题,请尝试改用 proc_open,因为某种原因,当我使用 proc_open 时,docker-compose bash 知道外部终端的大小,但是当我使用 passthru 时,它会丢失该信息。

例如,我将
<?php
passthru
("docker-compose -f docker-compose.yml bash",$ret);
?>
替换为
<?php
$empty1
=array();
$empty2=array();
$proc=proc_open("docker-compose -f docker-compose.yml bash",$empty1,$empty2 );
$ret = proc_close($proc);
?>

突然之间,docker-compose bash 就知道我的终端大小了 :)
bboy dot ru 的 igor
19 年前
如果您使用 passthru() 下载文件(对于动态生成的内容或 Web 服务器根目录之外的内容),并使用类似的代码

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

并且您的下载顺利完成,但是随后的下载/链接点击却乱了套,标题和二进制数据散布在整个网站上,请尝试添加

exit();

在 passthrough 之后。这将在下载完成后退出脚本,并且不会干扰任何将来的操作。
dtrasbo dot dk 的 mail
2 年前
要捕获命令的输出到字符串中而不使用输出缓冲函数,请使用 shell_exec()
novasonica dot com 的 tox
5 年前
我试图实现一个允许运行带有参数的任意 CLI 命令的系统,但我一直遇到命令的用户提示问题,因为它们会让执行挂起。解决方案很简单:只需使用 passthru(),因为它会输出所有内容并正确处理开箱即用的用户提示。
Zak Estrada
19 年前
请记住,使用 passthru 时要使用完整路径(例如 '/usr/local/bin/foo' 而不是 'foo'),否则您将收到错误代码 127(找不到命令)。
gmail dot com dot dfvuks 的 myselfasunder
14 年前
PHP 的程序执行命令在处理 STDERR 时会严重失败,并且 proc_open() 命令在 Windows 下的非阻塞模式下并不总是有效。

此命令虽然有用,但没有什么不同。要形成一个能够查看/捕获 STDOUT 和 STDERR 输出的机制,请将命令传递到 'tee' 命令(可以在 Windows 上找到),并将整个命令包装在输出缓冲中。

Dustin Oprea
envent dot co dot za 的 sarel dot w
19 年前
Zak Estrada
2004 年 12 月 14 日 11:21
请记住,使用 passthru 时要使用完整路径(例如 '/usr/local/bin/foo' 而不是 'foo'),否则您将收到错误代码 127(找不到命令)。

请记住,如果您的文件没有执行权限,您也会收到此错误。
Chroot
16 年前
如果您已经 chroot 了 apache 和 php,您还需要将 /bin/sh 放入 chroot 环境中。否则,exec() 或 passthru() 将无法正常运行,并将产生错误代码 127,文件未找到。
list dot ru 的 nuker
18 年前
我编写了一个函数,该函数从 Internet Explorer(从
注册表)获取代理服务器值。它在 Windows XP Pro 中经过测试

(对不起我的英语)

<?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; #无法访问注册表!非常糟糕…
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;
}

}
}
?>
注意,如果在Internet Explorer中禁用了代理,则此函数返回FALSE。
此函数仅返回HTTP代理服务器。

使用方法
<?php
$proxy
=getProxyFromIE();
if(!
$proxy)
echo
"无法获取代理!";
else
echo
$proxy;
?>
Stuart Eve
18 年前
我不知道其他人是否觉得这有用,但是当我尝试在Suse9.3上使用passthru()命令时,该命令没有成功。

$command = 'gdal_translate blahahahaha';

passthru($command);

只有在我添加以下内容后才有效:

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

passthru($command);
swbrown at ucsd dot edu
21年前
passthru() 似乎无论你做什么,都绝对会缓冲输出,即使使用了 ob_implicit_flush()。解决方案似乎是改用 popen()。
kpierre at fit dot edu
22年前
文档中没有提到 passthru() 只显示标准输出而不显示标准错误。

如果你正在运行脚本,你可以通过以下方式将 STDERR 管道到 STDOUT:

exec 2>&1

例如,下面的脚本将使用 passthru() 函数实际打印一些内容…

#!/bin/sh
exec 2>&1
ulimit -t 60
cat nosuchfile.txt
stuartc1 at NOSPAM dot hotmail dot com
19 年前
认为指出在 Windows 的 Dos 上运行时 passthru 似乎会抑制错误消息(在 NT 上测试)可能会有用。

要显示包括错误在内的完整原始输出,请使用 system()。
To Top