【问题标题】:how to interract with already-running php cli script from php cgi script如何从 php cgi 脚本与已经运行的 php cli 脚本交互
【发布时间】:2019-05-12 09:41:49
【问题描述】:

我制作了一个循环运行的 php cli 脚本。我从服务器的终端(Windows)运行它。该服务器还可以用作 php 网络服务器 (xampp)。

php cli 脚本处理硬件 i/o 内容(通过串行端口向微控制器板响应和提供逻辑)。一直在运行。

我想要完成的是制作一个基于 Web 的应用程序 (php cgi) 来控制该 cli 脚本。比如发送一些命令让它做某事。

我试过的

我尝试过使用一种临时 json 文件。哪些内容是由cgi脚本生成的。

然后 cli 脚本在每个循环中读取该文件。如果 json 有变化(时间戳),脚本会使用 json 中的数据来做相应的事情。然后存储该时间戳以将其与下一个循环的 json 进行比较。

但这会导致服务器上的巨大负载,并且 cli 脚本变得更慢。这会影响微控制器的响应能力。

php cli 循环是这样的。

<?php
$lastTimestamp=0;
while(true){
    //read json file
    $json=json_decode(file_get_contents("temp.json"));
    if($lastTimestamp < $json->stamp){
        //do something with $json->data
        ...
        //update $lastTimestamp
        $lastTimestamp = $json->stamp;
    }

    //rest of microcontroller logic here
    ...
}

temp.json 文件类似于

{
  "stamp": 1557653475,
  "data": {
    "nd_a": 1,
    "nd_b": 1,
    "nd_c": 0
  }
}

所以问题是如何在不使用上述方法的情况下与 cgi 脚本中已经运行的 php cli 脚本进行交互?期待一种不影响服务器负载和性能的更好方法。

编辑:我也尝试使用数据库代替 json 文件,但性能仍然不好。

【问题讨论】:

    标签: php command-line-interface server-side


    【解决方案1】:

    这种方式效率低下。最简单的方法是创建一个执行 cli 脚本的 cron 作业。 如果您使用的是 linux 系统,以下是设置 cron 的方法(在 Ubunutu 上) https://help.ubuntu.com/community/CronHowto

    然后在您的 cli 脚本中,删除循环,作业将读取 temp.json(每次作业运行时都会完成)并比较两个时间戳。

    现在,为了保留 $lastTimestamp,我建议在您的 cli 脚本旁边创建一个文本文件,并将 $lastTimestamp 的值存储在该文件中。 然后只有当从 json 中检索到的时间戳与文本文件中的时间戳存在差异时,才用新的时间戳覆盖文本文件。

    您可以使用 file_put_contents 或 fopen/fwrite 写入文件。

    所以你的脚本将如下所示

    <?php
    $lastTimestamp=0;
    $lastTimeStampFilePath = "lastTimeStampFile.txt";
    //read text file
    $lastTimestamp=file_get_contents($lastTimeStampFilePath);
    
        //read json file
        $json=json_decode(file_get_contents("temp.json"));
        if($lastTimestamp < $json->stamp){
            //do something with $json->data
            ...
            //update $lastTimestamp
            file_put_contents($lastTimeStampFilePath, $json->stamp);
        }
    
        //rest of microcontroller logic here
    

    可能会将作业配置为每 2 分钟或 5 分钟运行一次,具体取决于您的要求。

    【讨论】:

    • 感谢您的回答。但是脚本需要始终运行,因为它正在等待来自微控制器的串行通信,这可能随时发生。因此,使用带有间隔的 cron 可能会错过任何串行通信。也适用于那个 json 时间戳部分。这正是我现在正在做的事情。我期待诸如如何中断已经运行的脚本之类的东西。 node.js 中的 ipc 之类的东西。