我终于花时间实现了一个完整的解决方案,在一个简单的 NodeJS 服务器中使用 socket.io 进行广播。
在客户端,使用 Xterm.js 终端提供简单的 HTML
<script src='/socket.io/socket.io.js'></script>
<script src="xterm/xterm.js"></script>
...
<div class="terminal" id="terminal"></div>
并按照以下方式编写同步脚本
var socket = io();
term.open(document.getElementById('terminal'));
var updateTerminal = socket.on("updateTerminal", function(data) {
term.write(data);
});
现在data
可以传递给term.write
Xterm.js 的可以是原始终端数据。几个 UNIX 实用程序可以从终端监视这些原始数据,例如 tmux 由 jerch 在评论或脚本中提出。
要将这些数据传递给服务器进行广播,最简单的方法是使用命名管道;所以在服务器端
mkfifo server_pipe
script -f server_pipe
(发出最后一条命令的终端将是一个广播;如果一个人没有对服务器的物理访问权限,则可以使用额外的管道和隧道连接
mkfifo local_pipe
cat local_pipe | ssh <server> 'cat > path/to/server_pipe'&
script -f local_pipe
)
最后,NodeJS 服务器必须监听命名管道并广播任何新数据
/* create server */
const http = require('http');
const server = http.createServer(function (request, response) {
...
});
/* open named pipe for reading */
const fs = require('fs');
const fd = fs.openSync("path/to/server_pipe", 'r+')
const termStream = fs.createReadStream(null, {fd});
termStream.setEncoding('utf8');
/* broadcast any new data with socket.io */
const iolib = require("socket.io");
io = iolib(server);
termStream.on('data', function(data) {
io.emit("updateTerminal", data)
});
所有这些机制都在我的软件远程讲座中实现。
至于与视频广播的对比,我并没有花时间去实际量化差异,但是对于同等的分辨率和延迟,上述机制应该比捕获图形终端输出并与视频共享要少得多的网络和计算资源。