与 socket.io 的流互动 shell 会话
Stream interactive shell session with socket.io
我有 3 个组件 device
、server
和 frontend (admin)
。
服务器
使用 2 个命名空间 /admin
和 /client
启动 socket.io 服务器。
如果来自 /admin
命名空间的套接字发送数据,服务器会将其传递给 /client
命名空间。如果来自 /client
命名空间的套接字发送数据,服务器会将其传递给 /admin
命名空间。
const io = require('socket.io');
const device = io.of('/device');
const admin = io.of('/admin');
device.on('connection', (socket) => {
socket.on('data', (data) => {
console.log("PASSING DATA FROM [DEVICE] TO [ADMIN]")
admin.emit('data', data);
})
});
admin.on('connection', (socket) => {
socket.on('data', (data) => {
console.log("PASSING DATA FROM [ADMIN] TO [DEVICE]")
device.emit('data', data);
});
});
io.listen(80);
设备
使用 socket.io-client
连接到 socket.io
服务器。
使用 node-pty
.
开始交互式 shell 会话
const io = require('socket.io-client');
const socket = io('http://localhost:80/client');
const os = require('os');
const pty = require('node-pty');
const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash';
const ptyProcess = pty.spawn(shell, [], {
name: 'xterm-color',
cols: 80,
rows: 30
});
socket.on('connect', () => {
});
// INPUT DATA
socket.on('data', (data) => {
ptyProcess.write(data);
});
// OUTPUTING DATA
ptyProcess.onData = (data) => {
socket.emit('data', data)
}
前端
我终于有了使用 xterm.js
在浏览器中创建终端的前端。我正在使用 vue
。浏览器客户端也连接到 /admin
命名空间上的 socket.io
服务器。基本上我有这个:
<template>
<div id="app">
<div id="terminal" ref="terminal"></div>
</div>
</template>
<script>
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import { io } from 'socket.io-client';
export default {
mounted() {
const term = new Terminal({ cursorBlink : true });
term.open(this.$refs.terminal);
const socket = io('http://localhost:80/admin');
socket.on('connect', () => {
term.write('\r\n*** Connected to backend***\r\n');
term.onData((data) => {
socket.emit('data', data);
})
socket.on('data', (data) => {
term.write(data);
});
socket.on('disconnect', () => {
term.write('\r\n*** Disconnected from backend***\r\n');
});
});
}
}
</script>
问题
❌ 启动 pty 会话似乎有效,至少现在报告了错误。然而,似乎 onData
侦听器回调从未被触发,即使我 ptyProcess.write()
something.
❌ 从 xterm
一直获取设备 ptyProcess.write
的输入似乎不起作用。我可以看到数据通过 socket.io 套接字一直传递到设备。但是从那里什么也没有发生。我想念什么?我也没有在 xterm
window 中看到我的输入。
从 child_process
切换到使用 node-pty
创建交互式 shell 会话后,我几乎做对了。在 node-pty
文档之后,它将 on('data')
事件处理程序标记为已弃用。相反,我应该使用进程的 .onData
属性 来注册回调。像这样:
ptyProcess.onData = function(data) {
socket.emit('data', data);
};
但这并没有起到任何作用。所以我切换回添加事件侦听器的过时方式:
ptyProcess.on('data', function(data) {
socket.emit('data', data);
});
现在我有一个工作的交互式 shell 会话通过浏览器内的 websocket 从远程设备转发 ✅。
更新
为 onData
属性 进行了更多挖掘。意识到这不是 属性 而是一种方法,所以我用错了。这将是首选方式:
ptyProcess.onData(function(data) {
socket.emit('data', data);
});
这也符合预期
我有 3 个组件 device
、server
和 frontend (admin)
。
服务器
使用 2 个命名空间 /admin
和 /client
启动 socket.io 服务器。
如果来自 /admin
命名空间的套接字发送数据,服务器会将其传递给 /client
命名空间。如果来自 /client
命名空间的套接字发送数据,服务器会将其传递给 /admin
命名空间。
const io = require('socket.io');
const device = io.of('/device');
const admin = io.of('/admin');
device.on('connection', (socket) => {
socket.on('data', (data) => {
console.log("PASSING DATA FROM [DEVICE] TO [ADMIN]")
admin.emit('data', data);
})
});
admin.on('connection', (socket) => {
socket.on('data', (data) => {
console.log("PASSING DATA FROM [ADMIN] TO [DEVICE]")
device.emit('data', data);
});
});
io.listen(80);
设备
使用 socket.io-client
连接到 socket.io
服务器。
使用 node-pty
.
const io = require('socket.io-client');
const socket = io('http://localhost:80/client');
const os = require('os');
const pty = require('node-pty');
const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash';
const ptyProcess = pty.spawn(shell, [], {
name: 'xterm-color',
cols: 80,
rows: 30
});
socket.on('connect', () => {
});
// INPUT DATA
socket.on('data', (data) => {
ptyProcess.write(data);
});
// OUTPUTING DATA
ptyProcess.onData = (data) => {
socket.emit('data', data)
}
前端
我终于有了使用 xterm.js
在浏览器中创建终端的前端。我正在使用 vue
。浏览器客户端也连接到 /admin
命名空间上的 socket.io
服务器。基本上我有这个:
<template>
<div id="app">
<div id="terminal" ref="terminal"></div>
</div>
</template>
<script>
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import { io } from 'socket.io-client';
export default {
mounted() {
const term = new Terminal({ cursorBlink : true });
term.open(this.$refs.terminal);
const socket = io('http://localhost:80/admin');
socket.on('connect', () => {
term.write('\r\n*** Connected to backend***\r\n');
term.onData((data) => {
socket.emit('data', data);
})
socket.on('data', (data) => {
term.write(data);
});
socket.on('disconnect', () => {
term.write('\r\n*** Disconnected from backend***\r\n');
});
});
}
}
</script>
问题
❌ 启动 pty 会话似乎有效,至少现在报告了错误。然而,似乎 onData
侦听器回调从未被触发,即使我 ptyProcess.write()
something.
❌ 从 xterm
一直获取设备 ptyProcess.write
的输入似乎不起作用。我可以看到数据通过 socket.io 套接字一直传递到设备。但是从那里什么也没有发生。我想念什么?我也没有在 xterm
window 中看到我的输入。
从 child_process
切换到使用 node-pty
创建交互式 shell 会话后,我几乎做对了。在 node-pty
文档之后,它将 on('data')
事件处理程序标记为已弃用。相反,我应该使用进程的 .onData
属性 来注册回调。像这样:
ptyProcess.onData = function(data) {
socket.emit('data', data);
};
但这并没有起到任何作用。所以我切换回添加事件侦听器的过时方式:
ptyProcess.on('data', function(data) {
socket.emit('data', data);
});
现在我有一个工作的交互式 shell 会话通过浏览器内的 websocket 从远程设备转发 ✅。
更新
为 onData
属性 进行了更多挖掘。意识到这不是 属性 而是一种方法,所以我用错了。这将是首选方式:
ptyProcess.onData(function(data) {
socket.emit('data', data);
});
这也符合预期