终端共享工具实现原理:如何把 Shell 搬进浏览器

数据分析师Leo 专家 1小时前 更新于 2026年7月27日 713 浏览 12 点赞 约 2 分钟

远程协作调试最痛苦的不是改 Bug,而是通过视频会议看队友共享屏幕,4K 屏幕被压缩成马赛克,11px 的等宽字体简直是视觉折磨。其实用 ttyd 或 sshx 这种工具直接把终端映射到浏览器里才是正解,对方看到的是真实的文本,能直接复制粘贴。

终端共享工具实现原理:如何把 Shell 搬进浏览器

拆解这类工具的底层逻辑,核心其实就在于 PTY(伪终端)。

当你运行 bash 时,它并不是直接跟键盘对话,而是在和一个由内核模拟的「文件」通信。这个 PTY 分为 Master(主端)和 Slave(从端)。终端模拟器拿着 Master,Bash 拿着 Slave。只要一个程序能拿到 Master 端,把里面的字节流转发到网络上,就能实现远程控制。

以 sshx 的 Rust 实现为例,在 crates/sshx/src/terminal/unix.rs 中可以看到它如何操作:

终端共享工具实现原理:如何把 Shell 搬进浏览器

use nix::pty::{self, Winsize};
use nix::unistd::{execvp, fork, ForkResult, Pid};
use nix::libc::{login_tty, TIOCGWINSZ, TIOCSWINSZ};

pub struct Terminal {
 child: Pid,
 master_read: File,
 master_write: File,
}

逻辑很简单:先 fork 一个子进程,在子进程里调用 login_tty 让 Slave fd 成为控制终端,然后 execvp 启动 Shell,而父进程则死死把持着 Master 端。

终端共享工具实现原理:如何把 Shell 搬进浏览器

在实际部署和使用中,一个极易被忽视的细节是窗口尺寸同步。当你调整浏览器窗口大小时,后端必须通过 TIOCSWINSZ 这个 ioctl 调用来更新终端大小。如果这个环节出问题,你在浏览器里打开 vim 时,界面会直接崩掉或出现严重的渲染错位。

至于数据怎么传,ttyd 的做法极其暴力且高效。它直接用 C 语言写了一个基于 libwebsockets 的服务器,定义了一套极其简单的单字节 Opcode 协议:

// 客户端 -> 服务器
#define INPUT '0'
#define RESIZE_TERMINAL '1'
#define PAUSE '2'
#define RESUME '3'
#define JSON_DATA '{'

![终端共享工具实现原理:如何把 Shell 搬进浏览器](/uploads/articles/ac68d92e1c5bfb93.jpg)

// 服务器 -> 客户端
#define OUTPUT '0'
#define SET_WINDOW_TITLE '1'
#define SET_PREFERENCES '2'

这种设计几乎没有协议开销,'0' 后面直接跟按键或输出内容。为了防止 cat 一个大文件导致浏览器端被数据流冲垮,它还设计了 PAUSERESUME 机制来做背压控制。

这种把 PTY 字节流直接映射到 Web 端的方案,比传统的 VNC 或远程桌面轻量得多,是开发者远程协作的实战首选。

AI编程AI编程实战productivitywebdevprogramming

全部回复 (3)

副业中测试 中级 9小时前
直接用VS Code Live Share不香吗?非得搞这么麻烦。
0 回复
脚本小子阿强 初级 9小时前
确实,以前用远程桌面看代码眼睛都要瞎了,现在直接发个链接方便多了。
0 回复
运营喵小柯 中级 9小时前
我平时用ttyd配个简单的auth,不然链接随便传太危险了。
0 回复

发表回复

支持 Markdown 格式