Capture/supress 来自 php exec 的所有输出,包括 stderr
Capture/supress all output from php exec including stderr
我想通过 exec()
运行 几个命令,但我不希望任何输出到屏幕。但是,我确实想保留输出,以便我可以控制脚本的冗长程度 运行s.
这是我的 class:
<?php
class System
{
public function exec($command, array &$output = [])
{
$returnVar = null;
exec($command, $output, $returnVar);
return $returnVar;
}
}
问题是,大多数应用程序都会在 stderr
中放入大量不相关的东西,我似乎无法阻止。例如,这是 运行ning git clone
通过它的输出:
Cloning into '/tmp/directory'...
remote: Counting objects: 649, done.
remote: Compressing objects: 100% (119/119), done.
remote: Total 649 (delta 64), reused 0 (delta 0), pack-reused 506
Receiving objects: 100% (649/649), 136.33 KiB | 0 bytes/s, done.
Resolving deltas: 100% (288/288), done.
Checking connectivity... done.
我看到其他问题声称使用输出缓冲区可以工作,但它似乎不起作用
<?php
class System
{
public function exec($command, array &$output = [])
{
$returnVar = null;
ob_start();
exec($command, $output, $returnVar);
ob_end_clean();
return $returnVar;
}
}
这仍然会产生相同的结果。我 可以 通过在命令中将 stderr 路由到 stdout 来解决问题,但是,这不仅使我无法区分 stdout 和 stderr,而且此应用程序旨在 运行 Windows 和 Linux,所以现在这是一团糟。
<?php
class System
{
public function exec($command, array &$output = [])
{
$returnVar = null;
// Is Windows
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
exec($command, $output, $returnVar);
return $returnVar;
}
// Is not windows
exec("({$command}) 2>&1", $output, $returnVar);
return $returnVar;
}
}
有没有办法分别捕获和抑制 stderr 和 stdout?
更新/回答示例
根据评论中@hexasoft 的建议,我将方法更新为如下所示:
<?php
class System
{
public function exec($command, &$stdOutput = '', &$stdError = '')
{
$process = proc_open(
$command,
[
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
],
$pipes
);
if (!is_resource($process)) {
throw new \RuntimeException('Could not create a valid process');
}
// This will prevent to program from continuing until the processes is complete
// Note: exitcode is created on the final loop here
$status = proc_get_status($process);
while($status['running']) {
$status = proc_get_status($process);
}
$stdOutput = stream_get_contents($pipes[1]);
$stdError = stream_get_contents($pipes[2]);
proc_close($process);
return $status['exitcode'];
}
}
这项技术开辟了更多高级选项,包括异步进程。
命令 proc_exec()
允许使用管道处理执行命令的文件描述符。
函数为:proc_open ( string $cmd , array $descriptorspec , array &$pipes […optional parameters] ) : resource
你在 $cmd 中给你命令(如在 exec
中),你给一个描述文件描述符的数组给 "install" 命令。该数组由文件描述符编号 (0=stdin, 1=stdout...) 索引并包含类型 (file, pipe) 和模式 (r/w...) 加上文件类型的文件名。
然后您在 $pipes 中得到一个文件描述符数组,可用于读取或写入(取决于请求的内容)。
你不应该忘记在使用后关闭这些描述符。
请参阅 PHP 手册页(尤其是示例):https://php.net/manual/en/function.proc-open.php
请注意 read/write 与生成的命令有关,而不是 PHP 脚本。
我想通过 exec()
运行 几个命令,但我不希望任何输出到屏幕。但是,我确实想保留输出,以便我可以控制脚本的冗长程度 运行s.
这是我的 class:
<?php
class System
{
public function exec($command, array &$output = [])
{
$returnVar = null;
exec($command, $output, $returnVar);
return $returnVar;
}
}
问题是,大多数应用程序都会在 stderr
中放入大量不相关的东西,我似乎无法阻止。例如,这是 运行ning git clone
通过它的输出:
Cloning into '/tmp/directory'...
remote: Counting objects: 649, done.
remote: Compressing objects: 100% (119/119), done.
remote: Total 649 (delta 64), reused 0 (delta 0), pack-reused 506
Receiving objects: 100% (649/649), 136.33 KiB | 0 bytes/s, done.
Resolving deltas: 100% (288/288), done.
Checking connectivity... done.
我看到其他问题声称使用输出缓冲区可以工作,但它似乎不起作用
<?php
class System
{
public function exec($command, array &$output = [])
{
$returnVar = null;
ob_start();
exec($command, $output, $returnVar);
ob_end_clean();
return $returnVar;
}
}
这仍然会产生相同的结果。我 可以 通过在命令中将 stderr 路由到 stdout 来解决问题,但是,这不仅使我无法区分 stdout 和 stderr,而且此应用程序旨在 运行 Windows 和 Linux,所以现在这是一团糟。
<?php
class System
{
public function exec($command, array &$output = [])
{
$returnVar = null;
// Is Windows
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
exec($command, $output, $returnVar);
return $returnVar;
}
// Is not windows
exec("({$command}) 2>&1", $output, $returnVar);
return $returnVar;
}
}
有没有办法分别捕获和抑制 stderr 和 stdout?
更新/回答示例
根据评论中@hexasoft 的建议,我将方法更新为如下所示:
<?php
class System
{
public function exec($command, &$stdOutput = '', &$stdError = '')
{
$process = proc_open(
$command,
[
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
],
$pipes
);
if (!is_resource($process)) {
throw new \RuntimeException('Could not create a valid process');
}
// This will prevent to program from continuing until the processes is complete
// Note: exitcode is created on the final loop here
$status = proc_get_status($process);
while($status['running']) {
$status = proc_get_status($process);
}
$stdOutput = stream_get_contents($pipes[1]);
$stdError = stream_get_contents($pipes[2]);
proc_close($process);
return $status['exitcode'];
}
}
这项技术开辟了更多高级选项,包括异步进程。
命令 proc_exec()
允许使用管道处理执行命令的文件描述符。
函数为:proc_open ( string $cmd , array $descriptorspec , array &$pipes […optional parameters] ) : resource
你在 $cmd 中给你命令(如在 exec
中),你给一个描述文件描述符的数组给 "install" 命令。该数组由文件描述符编号 (0=stdin, 1=stdout...) 索引并包含类型 (file, pipe) 和模式 (r/w...) 加上文件类型的文件名。
然后您在 $pipes 中得到一个文件描述符数组,可用于读取或写入(取决于请求的内容)。
你不应该忘记在使用后关闭这些描述符。
请参阅 PHP 手册页(尤其是示例):https://php.net/manual/en/function.proc-open.php
请注意 read/write 与生成的命令有关,而不是 PHP 脚本。