从PHP脚本运行PHP脚本的最佳做法是什么?

时间:2015-07-22 08:59:43

标签: php linux shell-exec

我使用以下代码:

$SERVER_PATH = dirname(__FILE__);
shell_exec($PHP_LOCATION.' '.$SERVER_PATH."/script.php?k1=v1&k2=v2 > /dev/null 2>/dev/null &");

其中:

  • $PHP_LOCATION应包含PHP的路径,

  • $SERVER_PATH - 是当前工作目录(幸运的是,要运行的脚本位于同一目录中),

  • > /dev/null 2>/dev/null &已添加以使此调用异步(取自Asynchronous shell exec in PHP问题)

此代码有两个问题:

  1. 据我所知,?k1=v1&k2=v2仅适用于网络电话,因此在此特定情况下,参数不会传递给脚本。

  2. 我真的不知道如何初始化$PHP_LOCATION变量以使其灵活并适用于大多数主机。

  3. 我对这两个问题进行了一些研究:

    要解决 1 suggested使用-- 'parameters_string',但建议修改脚本以解析看起来有点笨拙的参数字符串。有更好的解决方案吗?

    要解决 2 ,我发现solution使用PHP_BINARY,但这是一个PHP 5.4+案例(我使用5.3)。但最初的问题是要运行与原始脚本版本相同版本的PHP。所以对我来说(因为我只使用PHP 5.3)可能有解决方案吗?

    编辑0

    让我解释为什么我坚持这种奇怪的(对于PHP)方法:

    这些PHP脚本应该彼此分开:

    • 其中一个将分析数据和

    • 第二个将生成PNG图作为最终结果。

    这些脚本并不打算同时运行,这意味着第二个脚本可以按照自己的计划运行,只需要运行应该在其数据准备就绪时(由第一个脚本)。因此,不应将数据从第二个脚本(子)传递回第一个(父)。

    编辑1

    从大多数评论中可以看出,主要讨论是分叉方向。但是,我想在原始问题中强调要点 1 2 。我有一些理由以我指出的方式解决任务,我试图指出所有这些原因。如果我的一些观点看起来很奇怪,请发表评论 - 我会更清楚,或者我会更改主要问题。

    提前谢谢!

1 个答案:

答案 0 :(得分:2)

如何获取可执行文件

假设您使用的是Linux,则可以使用:

function getBinaryRunner($binary)
{
    return trim(shell_exec('which '.$binary));
}

例如,同样可以用于检查是否安装了所需的东西:

function checkIfCommandExists($command)
{
    $result = shell_exec('which '.$command);
    return !empty($result);
}

有些观点:

  • 是的,它只适用于Linux
  • 如果允许将用户输入传递给shell命令,则应该小心:escapeshellarg()和公司
  • 事实上,通常PHP不应该用于这样的事情,就像它是关于异步请求一样,更好地实现分叉或运行来自外部工作者的命令。

如何传递参数

通过文件系统路径执行shell_exec()您正在访问该文件,显然,所有“GET”参数都只是文件名的一部分,它不再是“URI”,因为没有网络 - 服务器来处理它。所以你有两个选择:

  • 通过访问您的网络服务器来调用呼叫。所以它会像:

    //Yes, you will use wget or, better, curl to make web-request from CLI
    shell_exec('wget http://your.web-server.domain/script.php?foo=bar');
    

    这里有一个缺点:如果你通过公共DNS访问你的网络服务器,它将导致网络差距和所有处理开销。好处 - 显然,您不必期望脚本中的任何其他内容,也不必区分CLI和非CLI调用

  • 在脚本中使用$_SERVER数组,并使用CLI传递参数:

    shell_exec('/usr/bin/php /path/to/script.php foo bar');
    
    //inside your script.php you will see:
    //$_SERVER['argv'][0] is "script.php"
    //$_SERVER['argv'][1] is "foo"
    //$_SERVER['argv'][2] is "bar"
    

    是的,它需要在脚本中进行修改,并且可能需要一些如何映射“常规”Web请求和CLI的逻辑。我建议甚至考虑将与CLI相关的东西分离到不同的脚本包中,这样就不会弄乱那些逻辑。

有关“异步运行”的更多信息

执行php script.php &时,只需在后台模式下运行即可。但是,这仍然保持了您的过程的亲子关系。这意味着 - 如果父进程死亡,它的子进程也将被删除。确切地说,将触发SIGHUP并避免这种情况,您应该使用nohup命令。它将允许模拟流程的“分离”,从而使其运行可靠且独立于父流程发生的情况。