Non-blocking on STDIN in PHP CLI

主宰稳场 提交于 2020-01-28 04:07:45

问题


Is there anyway to read from STDIN with PHP that is non blocking:

I tried this:

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

and this:

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

but it still blocks until fread gets some data.

I noticed a few open bug reports about this (7 years old), so if it can't be done, does any one know any crude hacks that could accomplish this (on Windows and Linux)?

  • https://bugs.php.net/bug.php?id=34972
  • https://bugs.php.net/bug.php?id=47893
  • https://bugs.php.net/bug.php?id=48684

回答1:


Here's what I could come up with. It works fine in Linux, but on Windows, as soon as I hit a key, the input is buffered until enter is pressed. I'm currently trying to find a way to disable buffering on a stream, or specifically on STDIN in PHP.

<?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
    }
}

?>



回答2:


Just a notice, that non blocking STDIN working, now.




回答3:


Petah, I can't help with the PHP side of this directly, but I can refer you to an article I ran across a while ago in which someone emulated transistors by testing within a shell script for the existence of pending data for a named pipe. It's a fascinating read, and takes shell scripting to a whole new level of geekiness. :-)

The article is here: http://www.linusakesson.net/programming/pipelogic/

So ... in answer to your "crude hacks" request, I suppose you could shunt your stdio through named pipes, then exec() the tool whose source is included at the URL above to test whether anything is waiting to be sent through the pipe. You'd probably want to develop some wrapper functions to help with stuff.

I suspect the pipelogic solution is Linux-only, or at least would require a unix-like operating system. No idea how this could be accomplished on Windows.




回答4:


system('stty cbreak');
while(true){
    if($char = fread(STDIN, 1)) {
        echo chr(8) . mb_strtoupper($char);
    }
}


来源:https://stackoverflow.com/questions/9356152/non-blocking-on-stdin-in-php-cli

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!