使用 proc_open 时从 STDIN 管道读取

2023-11-23

我正在尝试制作一个网站,人们可以在线编译和运行他们的代码,因此我们需要找到一种交互式方式让用户发送指令。

其实大家首先想到的是exec() or system(),但是当用户想要输入某物时,这种方式就行不通了。所以我们必须使用proc_open().

例如下面的代码

int main()
{
    int a;
    printf("please input a integer\n");
    scanf("%d", &a);
    printf("Hello World %d!\n", a);
    return 0;
}

当我使用proc_open(), 像这样

$descriptorspec = array(      
0 => array( 'pipe' , 'r' ) ,  
    1 => array( 'pipe' , 'w' ) ,  
    2 => array( 'file' , 'errors' , 'w' ) 
);  
$run_string = "cd ".$addr_base."; ./a.out 2>&1";
$process = proc_open($run_string, $descriptorspec, $pipes);
if (is_resource($process)) {
    //echo fgets($pipes[1])."<br/>";
    fwrite($pipes[0], '12');
    fclose($pipes[0]);
    while (!feof($pipes[1]))
        echo fgets($pipes[1])."<br/>";
    fclose($pipes[1]);
    proc_close($process);
}

运行C代码时,我想获取第一个STDOUT流,并输入数字,然后获取第二个STDOUT流。但如果我取消注释行,该页面将被阻止。

有办法解决问题吗?当所有数据尚未放入管道时,如何从管道中读取数据?或者有没有更好的方法来编写这种交互程序?


它更多的是一个C or a glibc问题。你必须使用fflush(stdout).

为什么?和跑步有什么区别a.out在终端中并从 PHP 调用它?

答:如果你跑步a.out在终端(作为 stdin 和 tty)中,glibc 将使用行缓冲 IO。但是,如果您从另一个程序(在本例中为 PHP)运行它,并且它的 stdin 是一个管道(或其他但不是 tty),那么 glibc 将使用内部 IO 缓冲。这就是为什么第一个fgets()如果未注释则阻塞。欲了解更多信息,请检查此article.

好消息:您可以使用以下命令控制此缓冲stdbuf命令。改变$run_string to:

$run_string = "cd ".$addr_base.";stdbuf -o0 ./a.out 2>&1";

这是一个工作示例。即使 C 代码不关心也能工作fflush()因为它正在使用stdbuf命令:

启动子进程

$cmd = 'stdbuf -o0 ./a.out 2>&1';

// what pipes should be used for STDIN, STDOUT and STDERR of the child
$descriptorspec = array (
    0 => array("pipe", "r"),
    1 => array("pipe", "w"),
    2 => array("pipe", "w")
 );

// open the child
$proc = proc_open (
    $cmd, $descriptorspec, $pipes, getcwd()
);

将所有流设置为非阻塞模式

// set all streams to non blockin mode
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking(STDIN, 0);

// check if opening has succeed
if($proc === FALSE){
    throw new Exception('Cannot execute child process');
}

获取子进程 pid。我们稍后需要它

// get PID via get_status call
$status = proc_get_status($proc);
if($status === FALSE) {
    throw new Exception (sprintf(
        'Failed to obtain status information '
    ));
}
$pid = $status['pid'];

轮询直到子进程终止

// now, poll for childs termination
while(true) {
    // detect if the child has terminated - the php way
    $status = proc_get_status($proc);
    // check retval
    if($status === FALSE) {
        throw new Exception ("Failed to obtain status information for $pid");
    }
    if($status['running'] === FALSE) {
        $exitcode = $status['exitcode'];
        $pid = -1;
        echo "child exited with code: $exitcode\n";
        exit($exitcode);
    }

    // read from childs stdout and stderr
    // avoid *forever* blocking through using a time out (50000usec)
    foreach(array(1, 2) as $desc) {
        // check stdout for data
        $read = array($pipes[$desc]);
        $write = NULL;
        $except = NULL;
        $tv = 0;
        $utv = 50000;

        $n = stream_select($read, $write, $except, $tv, $utv);
        if($n > 0) {
            do {
                $data = fread($pipes[$desc], 8092);
                fwrite(STDOUT, $data);
            } while (strlen($data) > 0);
        }
    }


    $read = array(STDIN);
    $n = stream_select($read, $write, $except, $tv, $utv);
    if($n > 0) {
        $input = fread(STDIN, 8092);
        // inpput to program
        fwrite($pipes[0], $input);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 proc_open 时从 STDIN 管道读取 的相关文章

  • 显式删除会话cookie会产生什么影响?

    我使用 php session 来维护用户的会话 Session 在登录后创建 在注销或超时后销毁 我需要管理面板中的一个选项来强制注销任何用户 如果他在网站上处于活动状态 我怎样才能做到这一点 我正在考虑删除临时会话文件 这应该有效地破坏
  • PDO语法错误

    我在一个项目中使用 PDO 但提交时出现语法错误 这是我的代码
  • PHP 正则表达式匹配字符串的最后一次出现

    我的字符串是 text1 A373R12345 我想找到该字符串最后出现的非数字数字 所以我使用这个正则表达式 0 9 然后我得到这个结果 1 A373 2 12345 但我的预期结果是 1 A373R 它有 R 2 12345 另一个例子
  • PHP:将多字节字符串(单词)拆分为单独的字符

    尝试使用 mb split 将这个字符串 主楼怎么走 分割成单独的字符 我需要一个数组 但没有成功 有什么建议吗 谢谢你 例如 尝试使用带有 u 选项的正则表达式 chars preg split u string 1 PREG SPLIT
  • php中的$$是什么意思? [复制]

    这个问题在这里已经有答案了 变量后面的两个背对背 是什么意思 像这样 id 我在哪里可以找到更多相关信息 谢谢 In PHP 意味着您将给至少一名维护程序员带来多年的痛苦和折磨 请注意 您最终可能会成为维护程序员 它是一个可变变量 想象一下
  • 使用 phpdocx 下载损坏的 .docx

    我有一个项目 我们使用 phpdocx pro 在模板中生成 docx 文件 我可以很容易地将数据输入到模板中 但是当下载文件并在 MS Word 2010 中打开时 程序报告无法打开文件 因为内容存在问题 详细信息是 文件已损坏 并且无法
  • Laravel - 急切加载 Eloquent 模型的方法(而不是关系)

    就像我们可以急切加载 Eloquent 模型的关系一样 有没有办法急切加载不是 Eloquent 模型的关系方法的方法 例如 我有一个 Eloquent 模型GradeReport它有以下方法 public function totalSc
  • Zend Framework 中的动态默认模块

    有谁知道在 Zend Framework 中动态设置默认模块并且不会遇到命名空间问题的方法 例如 我想要做的是有一个允许加载的模块表 其中一个设置为默认模块 例如 我可能有 admin blog calendar 作为可以加载的模块 如果我
  • PHP - 警告:strpos() [function.strpos]: 空分隔符是什么意思?

    警告 strpos function strpos 空分隔符是什么意思 我有这个 if strpos 039 text false text str replace 039 text 猜测一下 我会说 text是一个空字符串 感谢马克指出细
  • 如何从脚本中创建新的 Joomla 用户帐户?

    我们正在为 Joomla 创建一个 XML API 允许合作伙伴网站在我们的网站上为其用户创建新帐户 我们已经创建了一个独立的 PHP 脚本来处理和验证 API 请求 但现在我们需要实际创建新帐户 我们最初只想进行 CURL 调用来提交注册
  • 纯基于网络的版本控制系统

    我的托管服务当前不允许在其服务器上运行 允许 svn git cvs 我真的希望能够将我的开发计算机上的当前源代码与我的生产服务器 同步 我正在寻找一个纯php python ruby版本控制系统 不只是一个client对于版本控制系统 不
  • PHP DOM - 剥离 span 标签,保留其内容

    我希望采用如下标记 span class test Some text that is strong bolded strong and contains a a href link a span 并在 PHP 中找到剥离跨度的最佳方法 剩
  • Laravel/00webhost 错误 404。在此服务器上找不到请求的 URL

    1 将我的文件上传到 000webhost 我将公用文件夹中的所有文件放置到公共 html然后我创建了一个名为laravel我在那里上传了所有其他文件 这是我的目录结构 laravel app 引导程序 config 公共 html 索引
  • PHP-docker容器中的环境变量

    我想在我的 docker 容器中显示一个环境变量 PHP 脚本如下所示 我使用 OpenShift 来启动容器 PHP 容器显示 env is 现在我更改容器的 dc 配置 oc env dc envar USER Pieter deplo
  • 如何在同一 PHP 页面上多次使用 mysqli fetch_assoc() 和准备好的语句?

    有没有办法启用fetch assoc 在同一页上多次使用准备好的语句 data conn gt prepare SELECT FROM some table WHERE id data gt bind param i id data gt
  • PHP 脚本不断执行 mmap/munmap

    我的 PHP 脚本包含一个循环 它只不过是回显和取消引用指针 如 tab othertab i gt 中的内容 直到昨天 这个脚本开始变得非常慢 比以前慢了 50 倍 之前 它一直运行良好 使用 strace 后 我发现 90 的情况下 脚
  • 合并 2 个数组并合并数字键的结果

    我有 2 个数组 我希望通过每个数字键将其中合并 分组在一起 例如 Array1 2009 gt 131 2008 gt 940 2007 gt 176 2006 gt 1 Array2 2008 gt 9 2007 gt 3 我希望输出是
  • 当我使用 session_start() 时,Xampp 7.0.1 Apache 崩溃

    当我在 PHP 中使用 session start 启动会话时 我的 Apache 服务器停止工作 我正在使用 Windows 版 Xampp 7 0 1 我的配置文件如下所示 即使我把它放在文件的第一行 它也不起作用 有人知道如何解决这个
  • 为什么这评估为 true

    为什么这评估结果为真
  • 如何将图像从 Android 应用程序上传到网络服务器的特定文件夹中

    如何将图像从 android 移动到 Web 服务器上的指定文件夹 这是我的安卓代码 package com example bitmaptest import java io ByteArrayOutputStream import ja

随机推荐

  • Android:TextView自动截断并替换字符串的最后3个字符

    If a String比TextView的宽度 它会自动换行到下一行 我可以通过使用来避免这种情况android singleLine 已弃用 或通过设置android inputType text 我现在需要的是替换我的最后 3 个字符的
  • 通过 PHP-fpm+nginx 没有可用的环境变量

    我尝试按以下方式修改 php ini variables order GPCSE register globals On 但所需要的PATH变量既不在 ENV也不能通过访问getenv PATH 我在跑Nginx PHP FPM on 乌班
  • perl regex 查找任何 5 的倍数的数字

    Perl 正则表达式查找任何 5 的倍数的数字 我尝试使用 5 但它只找到包含 5 的数字 而不是 5 的倍数 还可以查找长度为 5 的倍数的字符串 5 的倍数的数字要么以 5 要么以 0 结尾 尝试使用 d 05 意思是 字符串的开头 s
  • 以编程方式禁用/延迟 Android 锁屏

    我想disable delay以编程方式锁定屏幕 在研究这个问题时 KeyguardManager已折旧 不能持续工作 FLAG DISMISS KEYGUARD不是一个选项 因为我想在后台执行此操作 出于电池原因我不想使用 WakeLoc
  • 如何在pandas中将多种日期格式转换为一种格式

    我有以下 pandas 数据框 日期列为object ID Date Volume 0 13 02 2018 00 06 85 1 13 02 2018 00 10 70 2 13 02 2018 00 11 100 3 2018 02 1
  • 无法让 UICollectionView 显示单元格

    我试图让 UICollectionView 显示在模态呈现的视图控制器内 该应用程序适用于 iPad iOS 7 我创建了 UIViewController 的子类 带有笔尖 并像这样添加它 MyViewController control
  • 如何在 Cassandra 中创建自动增量 ID

    我们知道在SQL数据库中创建自增ID很容易 Cassandra中有没有好的解决方案 ID 应该用于键名或列名 创建全局数字序列在分布式系统中实际上没有任何意义 使用UUIDs 因为你必须让所有参与者都同意并接受序列的演变 在简单的实现下
  • HttpClient PostAsync 无效的帖子格式

    我正在尝试使用 HttpClient 的 PostAsync 登录网站 然而它总是失败 当我使用 WireShark 跟踪连接时 我发现它错误地发布了数据 Code var content new FormUrlEncodedContent
  • ADT插件安装问题Eclipse 3.7 Ubuntu 11.10 [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 我正在尝试为 Eclipse 3 7 和 Ubuntu
  • 我们可以使用 php 中的 ini_set() 函数将“allow_url_fopen”设置为“ON”吗?

    这个问题在这里已经有答案了 我们可以使用php中的ini set 函数将 allow url fopen 设置为 ON 吗 你不能 允许 url fopen 具有可变模式PHP INI SYSTEM Entry can be set in
  • iphone的TableView动态添加一行

    当我在表中选择一行时 我需要在表视图中添加新行 我应该使用以下方法吗 void insertRowsAtIndexPaths NSArray indexPaths withRowAnimation UITableViewRowAnimati
  • java.lang.ClassNotFoundException:org.apache.jsp.WEB_002dINF.pages.LandingPage_jsp

    打开项目时我遇到两个非常奇怪的错误 如果我打开登陆页面并不断刷新它 错误消息会在下面的两条消息之间交替显示 要么我得到这个 org apache jasper JasperException WEB INF pages LandingPag
  • 用于复杂写入的 Firebase 提交/回滚

    我正在使用 Firebase 编写一个金融应用程序 为了提交收据 还需要更新许多其他对象 为了使数据有效 所有数据更新都需要成功完成 如果其中一项写入出现错误 则必须回滚所有更新 例如 如果用户提交收据 则必须更新收据对象以及发票对象以及其
  • java.lang.VerifyError:在分支目标处期望有堆栈图帧

    成功编译了项目并使用 Maven 进行了构建 这是我的第一个 Maven 项目 但我不知道为什么会出现以下错误 在 tomcat 上部署战争并点击我的 url 浏览器中显示以下错误 java lang VerifyError Expecti
  • Android中,Handler是运行在主线程还是其他线程?

    我有以下代码 public class SplashScreen extends Activity private int splashTime 5000 Called when the activity is first created
  • ntext 数据的 GROUP BY

    我想看看场上有多少次MSGTEXT表中重复MMOUTBOUND 为此 我使用以下查询 SELECT MSGTEXT COUNT TotalCount FROM MMOUTBOUND GROUP BY MSGTEXT HAVING COUNT
  • Angular Material 日期选择器 - 仅月份和年份

    我希望我的角度材料日期选择器仅显示月份 年份 没有日子 这是我的日期选择器
  • Eclipse 中的 Grails 2.2.0 支持

    我正在尝试使用 eclipse jee juno 创建一个 grails 2 2 0 项目 它给了我一个错误 项目期望的 Groovy 编译器级别与工作区编译器级别不匹配 项目编译级别为 1 8 X 工作区编译器级别为 1 7 X 转到项目
  • Apache POI 加载 XSSFWorkbook 类时出错

    我正在尝试编写一个与 Excel 文档一起使用的程序 但 HSSF 格式对于我的要求来说太小了 我正在尝试转向 XSSF 但在尝试使用它时不断出现错误 我设法通过将 xmlbeans 2 3 0 jar 和 dom4j 1 6 jar 添加
  • 使用 proc_open 时从 STDIN 管道读取

    我正在尝试制作一个网站 人们可以在线编译和运行他们的代码 因此我们需要找到一种交互式方式让用户发送指令 其实大家首先想到的是exec or system 但是当用户想要输入某物时 这种方式就行不通了 所以我们必须使用proc open 例如