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

时间:2021-06-30 17:32:44
****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.

Ok I have a simple shell script that runs a command and outputs the FXO line voltages, normally you would have to get one line at a time this one combines them to one readable output. (irrelevant to this post but I thought someone might ask what this script does)

好的,我有一个简单的shell脚本,它运行一个命令并输出FXO线电压,通常情况下,你必须在一次将它们结合到一个可读的输出上。(与这篇文章无关,但我想有人可能会问这个剧本是做什么的)

This is the shell script:

这是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"

Running the script on the machine via the terminal it works great perfect really. In my PHP script I simply do this (the php script is on the same server as the sh file):

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

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

The output I recieve in the browser running the script is:

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

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

Now I have made sure that the permissions are correct, well should already know that since it runs 50% of the way, and like I have said I know that the script works on the machine.

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

It is just really weird because of the fact that it outputs the static text but not the dynamic text. The command 'wanpipemon -i w1g1 -c astats -m *' is part of the driver application for the analog card on my PBX and does not need root to run it (any user can run the command) so it confuses me as to what is going on.

这很奇怪,因为它输出静态文本而不是动态文本。这个命令的“wanpipemon -i - w1g1 -c astats -m *”是我的PBX上的模拟卡驱动程序的一部分,它不需要根来运行它(任何用户都可以运行这个命令),所以它让我对发生的事情感到困惑。

Any help and/or debugging advice will be much appreciated, thus far I have only tried double checking permissions on the shell script, running the script on the server in console (linesta.sh that is) but i am unsure what else to test. I have tried the other PHP commands such as exec() and system() with the exact same results.

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

2 个解决方案

#1


2  

Is wanpipemon in the path of whatever shell PHP's using to execute the script? The 'file not found' type errors would be written to stderr and not trapped by your string building in the script, and also not caught by PHP unless you did stderr redirection:

wanpipemon是否在任何shell PHP中执行脚本?“未找到的文件”类型错误将被写入stderr,而不会被脚本中的字符串构建所捕获,也不会被PHP捕获,除非您重定向stderr:

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

#2


1  

There are plenty of particular thing with shell_exec I use the following function to get all output

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()

#1


2  

Is wanpipemon in the path of whatever shell PHP's using to execute the script? The 'file not found' type errors would be written to stderr and not trapped by your string building in the script, and also not caught by PHP unless you did stderr redirection:

wanpipemon是否在任何shell PHP中执行脚本?“未找到的文件”类型错误将被写入stderr,而不会被脚本中的字符串构建所捕获,也不会被PHP捕获,除非您重定向stderr:

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

#2


1  

There are plenty of particular thing with shell_exec I use the following function to get all output

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()