Php 在web浏览器中模拟命令外壳输出 背景:

Php 在web浏览器中模拟命令外壳输出 背景:,php,ajax,Php,Ajax,现在,在我们公司,我们有一个基于PHP的应用程序来自动生成报告。它的工作原理如下: url="google.com" content=$(curl -L $url) echo $content 带有表单的网页会生成一个ini文件,其中包含一些本地保存的配置 PHP CLI脚本接受步骤1生成的ini文件,并基于该文件创建一个目录,其中包含从internet获取数据的文档。(需要5到10分钟才能完成) 另一个web表单探索文件夹的内容,进行一些验证,并将目录的内容显示为预览 在

现在,在我们公司,我们有一个基于PHP的应用程序来自动生成报告。它的工作原理如下:

url="google.com"
content=$(curl -L $url)
echo $content
  • 带有表单的网页会生成一个ini文件,其中包含一些本地保存的配置
  • PHP CLI脚本接受步骤1生成的ini文件,并基于该文件创建一个目录,其中包含从internet获取数据的文档。(需要5到10分钟才能完成)
  • 另一个web表单探索文件夹的内容,进行一些验证,并将目录的内容显示为预览
  • 在这些步骤之间,需要用户输入,有时用户需要中断脚本2以更正某些ini值


    问题: 我们希望在web浏览器中运行cli脚本,以便在用户单击“构建”按钮后,生成ini文件(或数组)并自动传递给第二个脚本。但是这个想法是让脚本独立运行(模拟另一个“线程”),详细描述它在执行过程中所做的一切,以便用户在需要时可以中断。类似于在命令行中运行脚本,其中每个步骤都是详细的


    我们建议使用AJAX,但它会在web浏览器中打印任何内容之前等待服务器完成其回答。 iFrame也不能工作,因为我们不能用javascript操作它的src属性和内容

    那么,我们如何“模拟”命令shell输出呢?任何方向正确的提示都将不胜感激

    注意:脚本将始终在“localhost”中使用,无需远程访问


    解决方案 根据这些建议,我最终做了一些更简单的事情:

    • 已将表单($\u POST)的内容转储到会话var$\u session['form']中
    • 创建了$_会话[form complete]标志,当用户单击“build”按钮时,该标志将设置为true
    • 如果$\u会话[form complete]为true,服务器将显示一个iframe,指向“CLI脚本”,其参数是以前转储的会话变量
    • CLI脚本还具有
      ob\u implicit\u flush(true);ob_end_flush()以便输出不会被缓存
    • 在脚本末尾,$\u SESSION变量是clean,会话被销毁
    iFrame也不能工作,因为我们不能用javascript操作它的src属性和内容

    如果iframe与父页面驻留在同一主机上(例如,
    localhost
    ),则可以。AJAX自然也不支持跨域请求,所以如果您使用AJAX,iFrame也会随之出现

    最简单的方法是将输出通过管道传输到,然后使用iframe/AJAX调用来检索输出。如果它在本地主机上运行,那么为此进行的带宽优化就没有意义了(除非日志变得很长)


    举个小例子: 假设我们要运行
    /long\u脚本
    。这就是我们可以做到的

  • system('./long_script>/tmp/file 2>&1&')(将所有输出传输到/tmp/file,然后在后台运行)

  • 制作一个类似这样的PHP脚本(您需要一种安全的获取文件名的方法,最好是一个会话变量,或者一个经过消毒的
    $\u GET
    变量):

    setTimeout(“window.location.reload()”,1000)

  • 将该PHP脚本放在iframe中。Javascript将导致每1s自动重新加载一次


  • 备选方案: 您可以使用来拥有一个进程句柄,然后将数据(set
    ob\u implicit\u flush(true)
    )刷新到浏览器中(这样它就不用等待从进程中获取所有输出,并一次推送所有输出)

    iFrame也不能工作,因为我们不能用javascript操作它的src属性和内容

    如果iframe与父页面驻留在同一主机上(例如,
    localhost
    ),则可以。AJAX自然也不支持跨域请求,所以如果您使用AJAX,iFrame也会随之出现

    最简单的方法是将输出通过管道传输到,然后使用iframe/AJAX调用来检索输出。如果它在本地主机上运行,那么为此进行的带宽优化就没有意义了(除非日志变得很长)


    举个小例子: 假设我们要运行
    /long\u脚本
    。这就是我们可以做到的

  • system('./long_script>/tmp/file 2>&1&')(将所有输出传输到/tmp/file,然后在后台运行)

  • 制作一个类似这样的PHP脚本(您需要一种安全的获取文件名的方法,最好是一个会话变量,或者一个经过消毒的
    $\u GET
    变量):

    setTimeout(“window.location.reload()”,1000)

  • 将该PHP脚本放在iframe中。Javascript将导致每1s自动重新加载一次


  • 备选方案: 您可以使用来拥有一个进程句柄,然后将数据(set
    ob\u implicit\u flush(true)
    )刷新到浏览器中(这样它就不用等待从进程中获取所有输出,并一次将其全部推送), 步骤2可以是这样的页面:

    url="google.com"
    content=$(curl -L $url)
    echo $content
    
    
    停止
    暂停
    ...
    这里的cli输出
    
    调用ajax(对PHP)将命令(停止、暂停)一些新信息(例如:新信息文件)写入“控制”文件

    定期检查step2cli.php中的“控制”文件。如果存在,解析并删除它,然后当然应用新信息。

    好, 步骤2可以是这样的页面:

    url="google.com"
    content=$(curl -L $url)
    echo $content
    
    
    停止
    暂停
    ...
    这里的cli输出
    
    调用ajax(对PHP)将命令(停止、暂停)一些新信息(例如:新信息文件)写入“控制”文件

    定期检查step2cli.php中的“控制”文件。如果存在,则解析它和rem