【问题标题】:How to call a bash function from PHP?如何从 PHP 调用 bash 函数?
【发布时间】:2016-02-01 19:04:02
【问题描述】:

这是我的工作流程:

ubuntu$ cat test.sh
#!/bin/bash

function getNumber
{
    echo 1
}


ubuntu$ cat test.php
<?php

echo shell_exec("getNumber");



ubuntu$ source test.sh 
ubuntu$ getNumber 
1

ubuntu$ php test.php 
sh: 1: getNumber: not found

是否可以改变一个 php 脚本(或者可能是它的调用)的方式,所以它会打印“1”?我正在寻找一种方法来从 php 调用 bash 函数

我从这里尝试了一些解决方案:Is it possible to source a *.sh file using PHP CLI and access exported Env vars in the PHP script?

其中一个是:./test.sh &amp;&amp; php -f test.php - 但没有运气。

【问题讨论】:

    标签: php bash


    【解决方案1】:

    这是一个可以满足您需求的功能。它加载生成一个 bash 进程,该进程获取 bash 脚本,然后运行该函数。

    它使用 proc-open (http://php.net/manual/en/function.proc-open.php)

    <?php
    
    
    $value = runBashFunction("test.sh", "getNumber");
    var_dump($value);
    
    
    
    function runBashFunction($bashfile, $bashfunction) {
        $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 too
        );
    
        $cwd = '.';
        $env = array();
    
        $process = proc_open('bash', $descriptorspec, $pipes, $cwd, $env);
    
        if (is_resource($process)) {
                fwrite($pipes[0], "source $bashfile\n");
                fwrite($pipes[0], "$bashfunction\n");
                fclose($pipes[0]);
    
                $output = stream_get_contents($pipes[1]);
                $error = stream_get_contents($pipes[2]);
                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 = proc_close($process);
                //note, $error and $return_value are discarded
                return $output;
        }
        return null;
    }
    ?>
    

    【讨论】:

    • 即使我在您的代码中将test.sh 重命名为不存在的test-whatever.sh,它也会始终打印int(1)
    • 糟糕,我返回的是 return_value 而不是输出。我已编辑脚本,请重试。
    • 谢谢你,@Tim。它看起来像它的作品。让我用一些参数试试。
    • 它适用于参数并且没有参数。它有点长,但我现在没有其他更好的工作解决方案。非常感谢!
    【解决方案2】:

    在这个特定示例中,您可以将 source 命令和函数本身组合到同一个 PHP exec 调用中:

    var_dump(
        shell_exec('source test.sh && getNumber')
    ); // string(2) "1
    "
    

    如果您需要删除回车,请修剪结果。

    【讨论】:

    • 这是它返回的内容...sh: 1: source: not found NULL
    • 你运行的是哪个操作系统?
    • Linux 3.13.0-37-通用 x86_64。 Linux Mint 17.1 丽贝卡
    • 但是 source test.sh &amp;&amp; getNumber 在您的控制台上工作?
    • 干杯 @TimSmith - 也许在命令中添加 bash 可能会缓解
    【解决方案3】:

    另一种方法是将要执行的函数的名称传递到 bash 脚本中。

    test.sh 是带有您要执行的功能的 bash 脚本:

    #!/bin/bash
    
    function getNumber
    {
        echo "fnGetNumber"
    }
    
    # Test if the first parameter names a function
    if [ "$(type -t $1)" = function ]; then
        $1
    else
        echo "$1 is an invalid function"
    fi;
    

    test.php 是调用该函数的 PHP 脚本:

    #!/usr/bin/php
    <?php
    echo `./test.sh getNumber`;
    

    请注意,这需要您传递脚本名称以及函数名称。

    功能测试致:https://stackoverflow.com/a/85903/2182349

    如果您想将参数传递给函数,您可以使用:

    更新了 test.sh

    #!/bin/bash
    
    function getNumber
    {
        echo "fnGetNumber $1"
    }
    
    if [ "$(type -t $1)" = function ]; then
        $1 "$2"
    else
        echo "$1 is an invalid function"
    fi;
    

    更新test.php

    <?php
    $parm = 'toast';
    echo `./test.sh getNumber $parm`;
    

    【讨论】:

    • 它确实有效,从技术上讲,我的问题得到了回答 - 有一个“虽然”:是否可以更改您的代码以便我可以将参数传递给 getNumber
    • 可能有多个(随机数)参数:)
    • 在 PHP 中将随机数量的参数括在引号中并将它们作为一个传递,然后在 bash 脚本中将它们分开。
    • 谢谢。我不认为总是可以将它们分开,尤其是当某些命令看起来像这样时rsync -aL --rsh="ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null" 我也无法触摸 bash 脚本(在我的问题中,我只能触摸 php 及其调用)。 shell 脚本是给我的一个库(函数列表),我无法更改它。 php 代码是我的 - 我可以随意进行任何我想要的更改。
    【解决方案4】:

    我找到了替代解决方案。问题出在 Ubuntu 及其 dash

    运行sudo dpkg-reconfigure dash 并回答nodash 更改为bash,是什么使source 命令可从php 获得。

    ls -la /bin/sh => /bin/sh -&gt; dash

    现在ls -la /bin/sh => /bin/sh -&gt; bash

    启用source 后,效果很好: echo shell_exec('source /full/path/to/file/test.sh &amp;&amp; getNumber abc def');

    对我有什么帮助: https://stackoverflow.com/a/13702876/4621324

    注意事项: 在更改期间 Ubuntu 警告我:使用 dash 作为系统 shell 将提高系统的整体性能。它不会改变呈现给交互式的 shell


    由于我真的不想在全球范围内将 dash 更改为 bash,因此我决定采用此解决方案:

    echo shell_exec('/bin/bash -c "source /full/path/to/file/test.sh &amp;&amp; getNumber abc def"');

    【讨论】:

      猜你喜欢
      • 2015-01-21
      • 1970-01-01
      • 2021-07-21
      • 2010-11-05
      • 1970-01-01
      • 2016-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多