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 将会挂起,直到程序执行结束。

参见

添加注释

用户贡献的注释 23 个注释

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

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

这将获取命令的所有输出,并退出而不向 stdout 发送任何数据。
jo at durchholz dot org
16 年前
注意 Paul Giblock:该命令*是*通过 shell 运行的。
您可以在任何 Linux 系统上通过以下方法验证这一点

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

您将获得 PATH 环境变量的内容,而不是字符串 $PATH。
divinity76+spam at gmail dot com
1 年前
如果您在使用 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 就知道了我的终端大小 :)
mail at dtrasbo dot dk
1 年前
要将命令的输出捕获到字符串中而不使用输出缓冲区函数,请使用 shell_exec()
igor at bboy dot ru
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);

并且您的下载正常进行,但后续的下载/链接点击出现故障,标题和二进制数据出现在整个网站上,请尝试在 passthrough 之后添加

exit();

这将在下载完成后退出脚本,并且不会影响任何未来的操作。
tox at novasonica dot com
4 年前
我试图实现一个允许运行具有参数的任意 CLI 命令的系统,但是我一直遇到来自命令的用户提示的问题,因为这些提示会让执行挂起。解决方案很简单:只需使用 passthru(),因为它会输出所有内容并正确处理用户提示。
Zak Estrada
19 年前
请记住,使用 passthru 时,请使用完整路径(例如 '/usr/local/bin/foo' 而不是 'foo'),否则您将获得退出代码 127(未找到命令)。
myselfasunder at gmail dot com dot dfvuks
13 年前
PHP 的程序执行命令在处理 STDERR 时会惨败,并且 proc_open() 命令在 Windows 下的非阻塞模式下并不总是那么有效。

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

Dustin Oprea
Chroot
16 年前
如果您使用 chrooted apache 和 php,那么您还需要将 /bin/sh 放入 chrooted 环境中。否则,exec() 或 passthru() 将无法正常工作,并将产生错误代码 127,文件未找到。
sarel dot w at envent dot co dot za
19 年前
Zak Estrada
14-Dec-2004 11:21
请记住,使用 passthru 时,请使用完整路径(例如 '/usr/local/bin/foo' 而不是 'foo'),否则您将获得退出代码 127(未找到命令)。

请记住,如果您的文件没有执行权限,您也会收到此错误。
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
nuker at list dot ru
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; #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;
}

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

用法
<?php
$proxy
=getProxyFromIE();
if(!
$proxy)
echo
"Can't get proxy!";
else
echo
$proxy;
?>
stuartc1 at NOSPAM dot hotmail dot com
19 年前
我认为记录 passthru 在 Windows 上的 Dos 中运行时似乎会抑制错误消息(在 NT 上测试)会很有用。

要显示包含错误的完整原始输出,请使用 system()。
Paul Giblock
17 年前
Stuart

pasthru 函数不会通过 shell 执行程序。这意味着,除其他事项外,你的 PATH 变量从未设置。因此,你必须对所有内容使用完整路径。

我相信 system() 会在 shell 下运行你的程序。这允许程序在“正常”环境中运行。

-Paul
vijayramanan at rediffmail dot com
18 年前
我在使用 exec 时遇到了问题。

我认为我们在 test.php 脚本上回显了信息。
例如:当我们尝试

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

返回结果为 127,并且代码失败。

检查此页面上的说明给了我们一个提示,建议使用 passthru 代替。
需要注意的唯一一点是,你需要提供完整路径。

现在我们的命令变成了

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

这有效。

耶!
sidney at jigsaw dot nl
23 年前
PJ 的 ulimit 示例很好;但是,如果你在 ulimit 命令之后在脚本中包含多个命令,每个命令都会获得一个单独的 60 秒时间段!<br>

此外,这 60 秒是 *CPU* 时间。大多数程序挂起的原因不是 CPU 占用过高(例如,等待数据库连接),因此对于大多数用途而言,数字 60 偏高。<br>

首先尝试 "ulimit -t 1",这将在现代硬件上提供大约 10^9 个周期——足够完成很多工作!
PJ at piggei dot com
23 年前
关于僵尸问题,你可以像这样调用 bash 脚本

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

<your command here>
--------------------------
me at yourMomsPussy dot cum
7 年前
`command` // 反引号将你从 PHP 模式带入 shell 模式
exec('command', $output); // exec 允许你将命令的返回值作为引用捕获
shell_exec('command'); // 将输出返回给变量
system(); // 如上所述。
php @ richud dot com
20 年前
关于 kpierre 的帖子,请注意,如果你的 shell 脚本出错,你会在 apache 的基本 error_log 文件(而不是虚拟主机 error_log 文件)中找到它的错误输出。
andreas dot hochsteger at oeamtc dot at
22 年前
如果你有时从 passthru() 中无法获得任何输出,请使用 system() 代替。这为我解决了这个问题(在使用 gcc 编译的 Tru64 Unix 上的 php 4.0.5)。
jcr at marvel-databadge dot com
20 年前
在 RH9 上的 apache 2.x 中,passthru() 每次写入 1 个字节。Apache 2.x 会为你缓冲和分块编码输出——但分块编码会将输出划分为每个 1 个字节的块...因此每个字节会有几个字节的开销。我想这种缓冲行为是设计好的——但给我使用 IE adobe acrobot 5 插件带来了问题。如果向它发送一个 1 个字节块流,插件不喜欢它——它会告诉你你的文件不是 pdf 或显示一个空白屏幕。使用输出缓冲 (ob_start / ob_endflush) 会产生合理大小的块,插件可以正常工作。
To Top