Захват / подавление всех выходных данных из php exec, включая stderr

Я хочу запустить несколько команд через exec() но я не хочу никакого вывода на экран. Я, однако, хочу сохранить вывод, чтобы я мог контролировать многословие во время выполнения моего скрипта.

Вот мой класс:

<?php
class System
{
public function exec($command, array &$output = [])
{
$returnVar = null;
exec($command, $output, $returnVar);
return $returnVar;
}
}

Проблема в том, что большинство приложений помещают раздражающее количество ненужных вещей в stderrкоторый я не могу заблокировать. Например, вот результат работы 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'];
}
}

Этот метод открывает гораздо более сложные возможности, в том числе асинхронные процессы.

4

Решение

команда proc_exec() позволяет работать с файловыми дескрипторами команды exec-ed, используя каналы.

Функция: resource proc_open ( string $cmd , array $descriptorspec , array &$pipes […optional parameters] )

Вы даете команду в $ cmd (как в exec) и вы даете массив, описывающий файловые дескрипторы для «установки» для команды. Этот массив индексируется по номеру файлового дескриптора (0 = стандартный ввод, 1 = стандартный вывод…) и содержит тип (файл, канал) и режим (r / w…) плюс имя файла для типа файла.

Затем вы получаете в $ pipe массив файловых дескрипторов, которые можно использовать для чтения или записи (в зависимости от того, что запрашивается).

Вы не должны забывать закрывать эти дескрипторы после использования.

Пожалуйста, обратитесь к странице справки по PHP (и, в частности, к примерам): http://php.net/manual/fr/function.proc-open.php

Обратите внимание, что чтение / запись относится к порожденной команде, а не к сценарию PHP.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]