从PHP运行没有输出

Boj*_*les 17 php exec

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成功.

  • 不好了!对不起,我不得不在SO和加勒比海盗之间做出选择;-) (5认同)

Fra*_*ula 8

这是一个使用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)

我希望这会有所帮助:-)