Неблокирование на STDIN в PHP CLI
В любом случае, читать с STDIN
с PHP, который не блокирует:
Я пробовал это:
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)?
Ответы
Ответ 1
Вот что я мог придумать. Он отлично работает в Linux, но в Windows, как только я нажимаю клавишу, вход буферизуется до нажатия клавиши ввода. В настоящее время я пытаюсь найти способ отключить буферизацию в потоке или, в частности, STDIN в 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
Просто заметьте, что не блокирующий STDIN работает, сейчас.
Ответ 3
Петах, я не могу помочь с этой частью PHP напрямую, но я могу отнести вас к статье, которую я провел некоторое время назад, когда кто-то эмулировал транзисторы путем тестирования внутри оболочки script для существования ожидающих данные для именованного канала. Это захватывающее прочтение, и он делает shell-скрипты совершенно новым уровнем geekiness.: -)
Статья находится здесь: http://www.linusakesson.net/programming/pipelogic/
Итак... в ответ на ваш запрос "грубые хаки", я полагаю, вы могли бы шунтировать свой stdio через именованные каналы, затем exec()
инструмент, источник которого включен по указанному выше URL, чтобы проверить, ожидает ли что-либо отправляется через трубу. Возможно, вам захочется разработать некоторые функции-обертки, которые помогут вам в работе.
Я подозреваю, что конвейерное решение Linux-only или, по крайней мере, потребует унифицированной операционной системы. Не знаю, как это можно сделать в Windows.
Ответ 4
system('stty cbreak');
while(true){
if($char = fread(STDIN, 1)) {
echo chr(8) . mb_strtoupper($char);
}
}