从PHP脚本运行PHP脚本的最佳实践是什么?

从PHP脚本运行PHP脚本的最佳实践是什么?,php,linux,shell-exec,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 &"); 其中: $SERVER_PATH = dirname(__FILE__); shell_exec($PHP_LOCATION.' '.$SERVER_PATH."/script.php?k1

我会使用以下代码:

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

$SERVER_PATH = dirname(__FILE__);
shell_exec($PHP_LOCATION.' '.$SERVER_PATH."/script.php?k1=v1&k2=v2 > /dev/null 2>/dev/null &");
  • $PHP\u LOCATION
    应包含指向PHP的路径

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

  • /dev/null 2>/dev/null&
    添加以使此调用异步(取自问题)

此代码有两个问题:

$SERVER_PATH = dirname(__FILE__);
shell_exec($PHP_LOCATION.' '.$SERVER_PATH."/script.php?k1=v1&k2=v2 > /dev/null 2>/dev/null &");
  • 就我所记得的
    ?k1=v1&k2=v2
    仅适用于web调用,因此在这种特殊情况下,参数不会传递给脚本

  • 我真的不知道如何初始化
    $PHP\u LOCATION
    变量以使其灵活并在大多数主机上工作

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

    $SERVER_PATH = dirname(__FILE__);
    shell_exec($PHP_LOCATION.' '.$SERVER_PATH."/script.php?k1=v1&k2=v2 > /dev/null 2>/dev/null &");
    
    要解决1问题,请使用
    --“parameters\u string”
    ,但也建议修改脚本以解析参数字符串,这看起来有点笨拙。有更好的解决办法吗

    为了解决2问题,我找到了一个可以使用
    PHP\u BINARY
    的方法,但这是一个PHP5.4+案例(我使用的是5.3)。但最初的问题是要运行与原始脚本版本相同版本的PHP。所以对我来说(因为我只使用PHP5.3),可能有解决方案吗

    编辑0

    让我解释一下为什么我坚持使用这种奇怪的(PHP)方法:

    这些PHP脚本应该彼此独立:

    • 其中一个将分析数据并

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

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

    编辑1

    从大多数评论来看,主要讨论的是分叉方向。然而,我想强调原始问题中提出的12这一点。我有一些理由以我指出的方式解决这项任务,我试图指出所有这些理由。如果我的一些观点看起来很奇怪,请发表评论——我会说得更清楚,或者我会改变主要问题

    提前谢谢你

    如何获取可执行文件 假设您使用的是Linux,您可以使用:

    function getBinaryRunner($binary)
    {
        return trim(shell_exec('which '.$binary));
    }
    
    例如,如果安装了所需的设备,则可以使用相同的方法进行检查:

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

    • 是的,它只适用于Linux
    • 如果允许将用户输入传递给shell命令:和company,则应小心处理用户输入
    • 事实上,通常情况下,PHP不应该用于类似于异步请求的东西,最好实现forking或运行来自外部工作者的命令
    如何传递参数 通过文件系统路径执行
    shell\u exec()
    ,您正在访问文件,显然,所有“GET”参数都只是文件名的一部分,它不再是“URI”,因为没有web服务器来处理它。所以你有两个选择:

    • 通过访问web服务器调用调用。所以它会像:

      //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访问您的web服务器,将导致网络间隙和所有处理开销。好处-显然,您不必期望脚本中有任何其他内容,也不必区分CLI调用和非CLI调用

    • 在脚本中使用数组,并按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&
    时,您只需在后台模式下运行它。然而,这仍然为您的流程保留了父子关系。这意味着-如果父进程死亡,它的子进程也将被删除。准确地说,将被触发,为了避免这种情况,您应该使用命令。它将允许模拟进程的“分离”,从而使其运行可靠且独立于父进程发生的情况。

    为什么不使用
    include_once('file path')
    ?@AbdoAdel我需要它是异步的。这就是为什么我想运行一个单独的进程。在
    include
    的情况下,在子进程完成之前,主脚本将无法获得控制。听起来PHP不是解决您当时试图解决的问题的最佳选择,线程语言是。我同意,@MartinBean,但现在我只能在PHP和JS上编写:(@MartinBean考虑到一个人可以在PHP中使用线程,这给我们留下了什么?我觉得你只是在用这个答案传播一个糟糕的设计。两个例子都不是异步的,这显然是这样做的原因。
    better to[…]运行来自外部工作者的命令
    -这应该是指导IMO的方向,正如我对这个问题的评论。我没有传播任何东西,因为我不建议将这种方式作为首选方式。OP仍然问了这个问题-根据情况,他可能需要或可能不需要实现分叉脚本进程。无论哪种方式,都是这样仅使用“纯CLI控制”就可以实现OP所需的功能,因此在某些情况下这可能很有价值info@AlmaDo感谢您提供如此详细的答案!我已将编辑0添加到原始问题中,以获得更多的澄清。问题是,所问问题的答案是
    shell_exec('nohup php/where.php args&')
    这只是答案所暗示的;我的意思是它无论如何都不会直接回答问题。我不否认这些信息