Я боролся с exec()
, пытаясь захватить вывод из него, когда добавляю задачу, используя команду системы Unix. Моя проблема заключается в том, что он не дает результата при запуске из моего сценария, однако его запуск с терминала и 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");
Однако, как только я использую, ничего не выводится. Как я могу получить вывод:
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
отключен, и я не могу понять, почему я не получаю никакого вывода с помощью входящего в echo оператора, когда выполнение atq
или любой другой комманды с exec()
дает мне вывод. Я искал и прочел этот вопрос , все безрезультатно.
Как я могу получить exec()
чтобы вернуть результат из строки или в строку или массив, если использовать второй аргумент с exec()
?
Я не понимал, что это может быть так просто. Все, что требуется, – это перенаправить 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, которые не захватываются exec. Я не уверен в этом, но рассмотрю возможность использования 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
теперь содержит все, что было напечатано в stderr (что должно действительно идти в stdout, потому что это не ошибка), а $return_value
содержит 0
при успехе.
Здесь более сложное решение с 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);
Надеюсь, это поможет 🙂
Попробуйте создать минимальный (не) рабочий пример. Разбейте все и испытайте только одно.
Вот одна ошибка в вашем bash:
hpek@melda:~/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 hpek@melda:~/temp$
Напишите minute
вместо minutes
.
Мой выход от присылается мне по почте!