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

如何在PHP的shell_exec()中指定虚拟终端大小?

解决shell_exec()中设置虚拟终端大小的问题

你的原有代码无效,是因为shell_exec默认使用管道而非伪终端(PTY),stty命令无法在管道环境下修改终端尺寸——程序(比如yum)是通过读取终端的TIOCGWINSZ属性来获取窗口大小的,只有在PTY环境下这个属性才能被修改。

要实现这个需求,应该用proc_open来创建带PTY的子进程,具体实现如下:

function shell_exec_with_pty_size(string $cmd, int $columns = 999, int $rows = 999): string
{
    $descriptorspec = [
        0 => ['pty'], // 标准输入绑定PTY
        1 => ['pty'], // 标准输出绑定PTY
        2 => ['pty']  // 标准错误绑定PTY
    ];

    $process = proc_open($cmd, $descriptorspec, $pipes);

    if (!is_resource($process)) {
        throw new RuntimeException('无法创建子进程');
    }

    // 获取PTY资源的文件描述符
    $pty_fd = (int) $pipes[0];

    // 构造TIOCSWINSZ结构体数据(Linux平台)
    $winsize = pack('S4', $rows, $columns, 0, 0);
    if (!defined('TIOCSWINSZ')) {
        define('TIOCSWINSZ', 0x5414);
    }
    fcntl($pty_fd, TIOCSWINSZ, $winsize);

    // 读取输出
    $output = stream_get_contents($pipes[1]);
    $error = stream_get_contents($pipes[2]);

    // 关闭管道和进程
    foreach ($pipes as $pipe) {
        fclose($pipe);
    }
    proc_close($process);

    // 合并标准输出和错误输出
    return $output . $error;
}

关键说明:

  • 使用proc_open创建带PTY的子进程,让目标程序认为自己运行在终端环境中。
  • 通过fcntl调用TIOCSWINSZ来设置PTY的窗口大小,这个系统调用会直接修改终端的尺寸属性,yum这类程序能正确读取到这个值。
  • 相比shell_exec,proc_open提供了对进程IO的更精细控制,确保PTY被正确绑定和配置。

针对yum的使用示例:

调用这个函数执行yum check-updates时,就能得到指定列数下的格式化输出:

$yum_output = shell_exec_with_pty_size('yum check-updates', 200, 999);
// 此时$yum_output会是列宽200下的单行格式,方便解析

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 05:20:29