exec()当我使用atUnix系统命令添加任务时,我一直在努力捕获它的输出.我的问题是,从我的脚本运行时它没有输出,但是从终端运行它并且 PHP在交互模式下打印出几行.
我想要执行的命令是这样的:
echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);
Run Code Online (Sandbox Code Playgroud)
var_dump()给出string(0) ""并print_r()吐出来Array ().我尝试使用shell_exec(),输出NULL,但在hi网页上下文中运行时,以下输出:
echo exec("echo 'hi'");
Run Code Online (Sandbox Code Playgroud)
这也输出了东西:
echo exec("atq");
Run Code Online (Sandbox Code Playgroud)
但是,一旦我使用at,就不会输出任何内容.我怎样才能获得以下输出:
exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);
Run Code Online (Sandbox Code Playgroud)
因为目前它通过Apache通过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
Run Code Online (Sandbox Code Playgroud)
safe_mode是关闭的,我无法弄清楚为什么我没有at使用管道输入回声声明获得任何输出,执行atq或任何其他推荐exec()给我输出.我搜索并阅读了这个问题,但都无济于事.
如果使用第二个参数,我怎样才能exec()将输出返回at到字符串或数组exec()?
Boj*_*les 27
我没有意识到这可能是这么简单.所需要的只是通过2>&1在命令的末尾执行来将stderr重新路由到stdout .现在任何输出at都打印到stdout,因此捕获exec():
echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes 2>&1", $result);
Run Code Online (Sandbox Code Playgroud)
我试图保持一个/两行解决方案,但最终唯一有用的是使用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);
}
Run Code Online (Sandbox Code Playgroud)
$output现在包含at打印到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;
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
// getting the mime type of a supplied file
echo runCommand('file -bi ' . escapeshellarg($file));
Run Code Online (Sandbox Code Playgroud)
另一个使用命令参数的示例:
// executing php code on the fly
echo runCommand('/usr/bin/php', '<?php echo "hello world!"; ?>');
Run Code Online (Sandbox Code Playgroud)
使用force参数的另一个示例(这对于将在执行过程中更改输出的命令非常有用):
// converting an mp3 to a wav file
echo runCommand('lame --decode ' . escapeshellarg($source) . ' ' . escapeshellarg($dest), '', true);
Run Code Online (Sandbox Code Playgroud)
我希望这会有所帮助:-)