在PHP CLI中对STDIN进行非阻塞

时间:2012-02-20 04:21:41

标签: stdin php

无论如何,使用非阻塞的PHP读取STDIN

我试过了:

stream_set_blocking(STDIN, false);
echo fread(STDIN, 1);

和此:

$stdin = fopen('php://stdin', 'r');
stream_set_blocking($stdin, false);
echo 'Press enter to force run command...' . PHP_EOL;
echo fread($stdin, 1);

但它仍会阻塞,直到fread获取一些数据。

我注意到一些有关此问题的公开错误报告(7岁),所以如果无法完成,是否有人知道任何可以实现此目的的粗暴黑客(在Windows和Linux上)?

4 个答案:

答案 0 :(得分:12)

这是我能想到的。它在Linux中工作正常,但在Windows上,只要我按下一个键,输入就会被缓冲,直到按下enter键。我目前正试图找到一种方法来禁用流上的缓冲,或者特别是在PHP中的STDIN上。

<?php

function non_block_read($fd, &$data) {
    $read = array($fd);
    $write = array();
    $except = array();
    $result = stream_select($read, $write, $except, 0);
    if($result === false) throw new Exception('stream_select failed');
    if($result === 0) return false;
    $data = stream_get_line($fd, 1);
    return true;
}

while(1) {
    $x = "";
    if(non_block_read(STDIN, $x)) {
        echo "Input: " . $x . "\n";
        // handle your input here
    } else {
        echo ".";
        // perform your processing here
    }
}

?>

答案 1 :(得分:1)

Petah,我无法直接帮助解决这方面的问题,但是我可以向您推荐一篇我之前跑过的文章,其中某人通过在shell脚本中测试是否存在待处理数据来模拟晶体管命名管道。这是一个引人入胜的阅读,并将shell脚本带入了一个全新的极客。 : - )

文章在这里:http://www.linusakesson.net/programming/pipelogic/

所以...在回答你的“粗暴黑客”请求时,我想你可以通过命名管道分流你的stdio,然后exec()工具的源代码包含在上面的URL中,以测试是否有任何东西在等待通过管道发送。你可能想要开发一些包装函数来帮助解决问题。

我怀疑pipelogic解决方案仅限Linux,或者至少需要类似unix的操作系统。不知道如何在Windows上实现这一目标。

答案 2 :(得分:1)

请注意,非阻塞STDIN正在工作,现在。

答案 3 :(得分:0)

display: inline-block;