从PHP运行没有输出

时间:2012-06-10 12:22:49

标签: php exec

我一直在与exec()搏斗,当我使用at 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()的{​​{1}},但是在网页上下文中运行后会输出NULL

hi

这也输出了东西:

echo exec("echo 'hi'");

但是,只要我使用echo exec("atq"); ,就不会输出任何内容。如何获得输出:

at

因为目前PHP通过Apache以“正常”运行时没有输出任何内容,但是在终端以及PHP的交互式控制台中运行命令会给我预期的结果:

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

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获取任何输出atq给了我输出。我搜索并阅读了this question,但都无济于事。

如果exec()使用第二个参数exec(),我如何让atexec()的输出返回到字符串或数组?

3 个答案:

答案 0 :(得分:27)

工作,一线解决方案

我没有意识到这可能是这么简单。所需要的只是通过将2>&1放在要执行的命令的末尾来将stderr重新路由到stdout。现在,at的任何输出都会打印到标准输出,因此会被exec()

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

我的旧解决方案:

我试图保持一个/两行解决方案,但最后唯一有用的是使用proc_open() ,因为at会记录到stderr,{{1} }不读!我要感谢@Tourniquet指出这一点,但是他已经删除了他的答案。引用:

  

据我所见,在输出到stderr时,未被捕获   EXEC。我对此并不是很有信心,但考虑使用   http://php.net/manual/en/function.proc-open.php,允许你这样做   直接stderr到自己的管道。

这实际上是正确的做事方式。我的解决方案(因为我只想要stderr)是这样做的:

exec()

// 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); } 现在包含打印到stderr的任何$output(这应该是stdout,因为它不是错误),at成功时包含$return_value

答案 1 :(得分: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;
}

用法示例:

// 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);

我希望这有助于: - )

答案 2 :(得分:0)

尝试创建最小(非)工作示例。打破一切,一次只测试一件事。

以下是您的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代替og minutes

at的输出是通过邮件发送给我的!