PHP 中高效监听标准输入按键的正确实现方法
#技术教程 发布时间: 2026-01-17
本文介绍如何解决 php 使用非阻塞 `fgets()` 监听 stdin 时导

在命令行 PHP 应用中,常需实时响应用户按键(如菜单导航、交互式工具),开发者常采用 fopen("php://stdin") 配合 stream_set_blocking(false) 实现非阻塞读取。但原始写法存在严重性能缺陷:
$stdin = fopen("php://stdin", "r");
stream_set_blocking($stdin, false);
system("stty cbreak -echo");
while (true) {
if ($keypress = strtoupper(fgets($stdin))) {
break;
}
}该循环会以极高速度反复调用 fgets() —— 当输入缓冲区为空时,fgets() 立即返回 false,CPU 在无休止的“检查→失败→再检查”中满载运行,造成 100% 占用,既耗电又影响系统响应。
✅ 推荐修复方案:引入微秒级休眠
通过 time_nanosleep(0, N) 在每次空读之后暂停指定纳秒数(如 5 毫秒 = 5,000,000 纳秒),可将 CPU 占用降至接近 0%,同时保持毫秒级响应灵敏度:
$stdin = fopen("php://stdin", "r");
stream_set_blocking($stdin, false);
system("stty cbreak -echo");
$t = 1000000; // 1 微秒 = 1000 纳秒 → 此处单位为纳秒
while (!($keypress = strtoupper(trim(fgets($stdin))))) {
time_nanosleep(0, 5 * $t); // 休眠 5 毫秒
}
// 恢复终端设置(关键!)
system("stty -cbreak echo");
stream_set_blocking($stdin, true);
fclose($stdin);⚠️ 注意事项:
- 必须调用 trim() 清除换行符,避免误判空行;
- stty cbreak -echo 关闭回显并启用单字符输入,退出前务必恢复(如 stty -cbreak echo),否则终端可能异常;
- time_nanosleep() 在 Windows 下不可用,生产环境建议封装兼容逻辑或改用 usleep(5000)(精度略低但跨平台);
- 若需更高可靠性,可结合 stream_select() 实现真正的 I/O 多路复用(需 PHP ≥ 7.4,且仅限 Unix-like 系统):
$read = [$stdin];
$write = $except = [];
if (stream_select($read, $write, $except, 0, 5000) > 0) {
$keypress = strtoupper(trim(fgets($stdin)));
}? 总结:非阻塞轮询必须配合适当延时,time_nanosleep() 是平衡响应性与资源消耗的简洁解法;长期项目建议抽象为可配置的 KeyReader 类,并增加超时、信号中断等健壮性处理。
技术教程SEO上一篇 : 兔喜生活便民服务网页版登录 兔喜生活服务浏览器版一键快速入口
下一篇 : iPhone 15如何开启语音唤醒Siri_iPhone 15 Siri设置教程
-
SEO外包最佳选择国内专业的白帽SEO机构,熟知搜索算法,各行业企业站优化策略!
SEO公司
-
可定制SEO优化套餐基于整站优化与品牌搜索展现,定制个性化营销推广方案!
SEO套餐
-
SEO入门教程多年积累SEO实战案例,从新手到专家,从入门到精通,海量的SEO学习资料!
SEO教程
-
SEO项目资源高质量SEO项目资源,稀缺性外链,优质文案代写,老域名提权,云主机相关配置折扣!
SEO资源
-
SEO快速建站快速搭建符合搜索引擎友好的企业网站,协助备案,域名选择,服务器配置等相关服务!
SEO建站
-
快速搜索引擎优化建议没有任何SEO机构,可以承诺搜索引擎排名的具体位置,如果有,那么请您多注意!专业的SEO机构,一般情况下只能确保目标关键词进入到首页或者前几页,如果您有相关问题,欢迎咨询!