You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP通过proc_open启动cu命令读取GSM调制解调器输出时fread挂起问题

问题原因

cu 属于交互式终端工具,默认交互场景下的状态输出(比如 Connected. 提示)是直接输出到控制终端(TTY),而非标准输出(STDOUT)或标准错误(STDERR)。你通过 proc_open 创建的管道不属于 TTY 设备,所以这部分输出根本没有进入你监听的 $pipes[1] 管道,自然读不到内容,导致阻塞。
而 cu -v 属于非交互的版本查询场景,输出直接写 STDOUT,所以可以正常通过管道读取。

解决方案
  • 方案1:使用伪终端(PTY)替代管道
    proc_open 支持指定 PTY 类型的描述符,模拟终端环境让 cu 正常输出内容,修改代码如下:
<?php
$descriptors = [
    0 => ['pty', 'r'],
    1 => ['pty', 'w'],
    2 => ['file', 'errors.txt', 'a']
];
$handle = proc_open('cu -s 115200 -l /dev/ttyUSB3', $descriptors, $pipes);
stream_set_blocking($pipes[1], 1);
$world = fread($pipes[1], 1);
var_dump($world);

注意:运行PHP脚本的用户需要拥有 /dev/ttyUSB3 的读写权限,建议将用户加入 dialout 用户组。

  • 方案2:直接操作串口设备(更推荐)
    不需要额外依赖 cu 工具,直接通过PHP读写串口设备,稳定性更高。
    首先通过 stty 配置串口参数:
    stty -F /dev/ttyUSB3 115200 cs8 -cstopb -parenb
    之后直接在PHP中操作:
<?php
$serial = fopen('/dev/ttyUSB3', 'r+');
stream_set_blocking($serial, 1);
// 可直接发送AT指令调试
fwrite($serial, "AT\r\n");
echo fread($serial, 1024);
  • 方案3:通过expect封装调用
    expect 工具天生适配交互式程序,会自动创建伪终端,你可以编写expect脚本捕获cu的输出,再通过PHP调用expect脚本获取结果。

内容的提问来源于stack exchange,提问作者Iain Dooley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 21:06:04