PHP shell_exec() - 不打印动态输出,只打印静态回显文本

时间:2011-07-21 17:38:51

标签: php linux shell

****UPDATE****
# The issue was within the wanpipemon script and the way that it interacts 
# with ioctl basically unless you want to edit the source for wanpipemon 
# and recompile it, it will not work. I have tried -S with root among 
# others and unless I am within console it throws a not authorized error 
# in the ioctl function.

好的我有一个简单的shell脚本运行命令并输出FXO线电压,通常你必须一次得到一行,这一行将它们组合成一个可读输出。 (与这篇文章无关,但我认为有人可能会问这个剧本的作用)

这是shell脚本:

#!/bin/bash

LINE1=$(wanpipemon -i w1g1 -c astats -m 1 | grep -m1 VOLT | cut -d ":" -f 2-2)
LINE2=$(wanpipemon -i w1g1 -c astats -m 2 | grep -m1 VOLT | cut -d ":" -f 2-2)
LINE3=$(wanpipemon -i w1g1 -c astats -m 3 | grep -m1 VOLT | cut -d ":" -f 2-2)
LINE4=$(wanpipemon -i w1g1 -c astats -m 4 | grep -m1 VOLT | cut -d ":" -f 2-2)
LINE5=$(wanpipemon -i w1g1 -c astats -m 5 | grep -m1 VOLT | cut -d ":" -f 2-2)
LINE6=$(wanpipemon -i w1g1 -c astats -m 6 | grep -m1 VOLT | cut -d ":" -f 2-2)

echo "Line 1 Voltage: $LINE1"
echo "Line 2 Voltage: $LINE2"
echo "Line 3 Voltage: $LINE3"
echo "Line 4 Voltage: $LINE4"
echo "Line 5 Voltage: $LINE5"
echo "Line 6 Voltage: $LINE6"

通过终端在机器上运行脚本,它确实非常完美。在我的PHP脚本中,我只是这样做(php脚本与sh文件在同一服务器上):

<?php
    $output = shell_exec('/usr/sbin/linesta.sh');
    echo "<pre>$output</pre>";
?>

我在运行脚本的浏览器中收到的输出是:

Line 1 Voltage:
Line 2 Voltage:
Line 3 Voltage:
Line 4 Voltage:
Line 5 Voltage:
Line 6 Voltage:

现在我确保权限是正确的,应该已经知道,因为它运行了50%,就像我说的那样,我知道脚本可以在机器上运行。

这真的很奇怪,因为它输出的是静态文本而不是动态文本。命令'wanpipemon -i w1g1 -c astats -m *'是我的PBX上模拟卡的驱动程序应用程序的一部分,并且不需要root运行它(任何用户都可以运行命令)所以它让我困惑的是什么正在进行。

我们非常感谢任何帮助和/或调试建议,到目前为止我只尝试了对shell脚本的双重检查权限,在控制台的服务器上运行脚本(linesta.sh)但我不确定还有什么去测试。我尝试过其他PHP命令,如exec()和system(),结果完全相同。

2 个答案:

答案 0 :(得分:2)

PHP用于执行脚本的shell的路径中是wanpipemon吗? “找不到文件”类型错误将被写入stderr并且不会被脚本中的字符串构建捕获,除非您执行stderr重定向,否则也不会被PHP捕获:

$output = shell_exec('/usr/sbin/linesta.sh 2>&1');
                                           ^^^^--- redirect stderr to stdout.

答案 1 :(得分:1)

shell_exec有很多特别之处我使用以下函数来获取所有输出

/**
 * Executes the shell command and gets stdout and stderr streams
 *
 * @see http://www.php.net/manual/en/function.proc-open.php
 * @param string $cmd - command to be executed
 * @param string $cwd - folder
 * @param array $env - options
 * @return array()
 */
function shexec($cmd, $cwd = './', $env = array())
{
    $return_value = array(
         "exit"   => 1,       // exit 0 on ok
         "stdout" => "",      // output of the command
         "stderr" => "",      // errors during execution
    );

    $descriptorspec = array(
    0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
    1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
    2 => array("pipe", "w")   // stderr is a pipe
    );

    $process = proc_open(escapeshellcmd($cmd), $descriptorspec, $pipes, $cwd, $env);
    // $pipes now looks like this:
    // 0 => writeable handle connected to child stdin
    // 1 => readable handle connected to child stdout
    // 2 => readable handle connected to child stderr

    if (false === is_resource($process))
    {
        //echo("Sys::shexec() Error on proc_open, shell command \"$cmd\"");
    }
    else
    {
        $return_value['stdout'] = stream_get_contents($pipes[1]);
        $return_value['stderr'] = stream_get_contents($pipes[2]);

        fclose($pipes[0]);
        fclose($pipes[1]);
        fclose($pipes[2]);

        // It is important that you close any pipes before calling
        // proc_close in order to avoid a deadlock
        $return_value['exit'] = proc_close($process);
    }

    if(trim($return_value['stderr']) !== "") {
        //echo("Sys::shexec() \n\"$cmd\"\nERROR:\n" . $return_value['stderr']);
    }

    if(trim($return_value['stdout']) !== "") {
        //echo("Sys::shexec() \n\"$cmd\"\nOUTPUT:\n" . $return_value['stdout']);
    }

    return $return_value;

} // END FUNCTION shexec()