Работа с PHP не дает результата

Я боролся с exec(), пытаясь захватить вывод из него, когда добавляю задачу с помощью системной команды at Unix. Моя проблема заключается в том, что он не выводит вывод при запуске из моего script, однако его запуск с терминала и PHP в интерактивном режиме выводит несколько строк.

Команда, которую я хочу выполнить, следующая:

echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);

var_dump() дает string(0) "", а print_r() выплескивает Array (). Я попытался использовать shell_exec(), который выводит NULL, однако следующие выходы hi при запуске в контексте веб-страницы:

echo exec("echo 'hi'");

Это также выводит материал:

echo exec("atq");

Однако, как только я использую at, ничего не выводится. Как я могу получить вывод:

exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);

Потому что в настоящее время он ничего не выводит при запуске как "обычный" через PHP через Apache, однако запуск команды в терминале, а также в интерактивной консоли PHP дает мне ожидаемый результат чего-то вроде:

php > echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);
warning: commands will be executed using /bin/sh
job 1219 at Sun Jun 10 12:43:00 2012

safe_mode выключен, и я не могу понять, почему я не получаю никакого вывода из at с помощью входящего в echo оператора, при выполнении atq или любой другой оценки с помощью exec() дает мне вывод, Я искал и читал этот вопрос, все это безуспешно.

Как я могу получить exec() для возврата вывода из at в строку или массив, если использовать второй аргумент с exec()?

Ответы

Ответ 1

Рабочее, однострочное решение

Я не понимал, что это может быть так просто. Все, что требуется, - это перенаправить stderr в stdout, поместив 2>&1 в конец выполняемой команды. Теперь любой вывод из at печатается на stdout, поэтому фиксируется exec():

echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes 2>&1", $result);

Мое старое решение:

Я пытался сохранить одно/двухстрочное решение, однако единственное, что работало в конце, заключалось в использовании proc_open() , потому что at записывается в stderr, который exec() не читает! Я хотел бы поблагодарить @Tourniquet за указание на это, однако он удалил свой ответ. Цитировать:

Насколько я могу видеть, на выходах на stderr, которые не фиксируются Отв. Я не уверен в этом, но http://php.net/manual/en/function.proc-open.php, что позволяет прямой stderr в свою собственную трубу.

На самом деле это правильный способ делать вещи. Мое решение (потому что я только хочу stderr) должно было сделать это:

// Open process to run `at` command
$process = proc_open("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", array(2 => array("pipe", "w")), $pipes);

// Get stuff from stderr, because `at` prints out there for some odd reason
if(is_resource($process)) {
    $output = stream_get_contents($pipes[2], 100);
    fclose($pipes[2]);

    $return_value = proc_close($process);
}

$output теперь содержит все at, напечатанные в stderr (что должно действительно идти в stdout, потому что это не ошибка), а $return_value содержит 0 при успешном завершении.

Ответ 2

Здесь более сложное решение с proc_open. Я пишу этот ответ, потому что в моем случае обходной путь "2 > и 1" не работает.

function runCommand($bin, $command = '', $force = true)
{
    $stream = null;
    $bin .= $force ? ' 2>&1' : '';

    $descriptorSpec = array
    (
        0 => array('pipe', 'r'),
        1 => array('pipe', 'w')
    );

    $process = proc_open($bin, $descriptorSpec, $pipes);

    if (is_resource($process))
    {
        fwrite($pipes[0], $command);
        fclose($pipes[0]);

        $stream = stream_get_contents($pipes[1]);
        fclose($pipes[1]);

        proc_close($process);
    }

    return $stream;
}

Примеры использования:

// getting the mime type of a supplied file
echo runCommand('file -bi ' . escapeshellarg($file));

Другой пример, используя параметр команда:

// executing php code on the fly
echo runCommand('/usr/bin/php', '<?php echo "hello world!"; ?>');

Другой пример с использованием параметра force (это может быть полезно для команд, которые будут изменять вывод во время процесса выполнения):

// converting an mp3 to a wav file
echo runCommand('lame --decode ' . escapeshellarg($source) . ' ' . escapeshellarg($dest), '', true);

Я надеюсь, что это поможет : -)

Ответ 3

Попробуйте создать минимальный (не) рабочий пример. Разбейте все, и одновременно проверяйте только одно.

Вот ваша ошибка в bash:

[email protected]:~/temp$ echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes
at: pluralization is wrong
job 22 at Sun Jun 10 14:48:00 2012
[email protected]:~/temp$ 

Напишите minute вместо og minutes.

Мой вывод из at отправляется мне по почте!