node.js - 在 node.js 中作为子进程运行 shell(bash, zsh, sh...)
问题描述
我正在制作一个在线外壳来从另一台计算机或设备访问我的计算机。我可以运行任何程序,使用 socket.io 发送和接收 stdio 数据。我使用 child_process 中的 execFile() 运行程序。问题是,当我尝试运行 bash、sh、zsh、csh 或任何其他 shell 时,它只是不起作用,没有错误消息或任何东西。如何在 node.js 中将 shell 作为子进程运行(更喜欢使用 execFile,但这没关系)?这是我正在使用的代码:
服务器:
let fs = require("fs");
let socket = require("socket.io");
let express = require("express");
let stringio = require("@rauschma/stringio");
let childprocess = require("child_process");
let app = express();
app.use(express.static("public"));
let server = app.listen(3000);
console.log("Server running!");
let io = socket(server);
io.sockets.on("connection", connectionListener);
function connectionListener(socket) {
console.log("New client!");
let child = childprocess.execFile("bash", ["test.sh"], {
stdio: [process.stdin, process.stdout, process.stderr]
});
socket.on("stdin-packet", sendtochild);
function sendtochild(packet) {
child.stdin.write(packet.rawtext);
}
child.stdout.on('data', function(data) {
let packet = {
rawtext: data.toString()
};
socket.emit("stdout-packet", packet);
console.log("Packet sended!");
});
}
客户:
let socket = io.connect("localhost:3000");
function TerminalScreen(width, height) {
this.width = width;
this.height = height;
this.chars = "";
this.print = function(text) {
let isansi = false;
for (let i = 0; i < text.length; i++) {
if (text.charCodeAt(i) == 27) {
isansi = true;
} else if (text.charAt(i) == 'm' || text.charAt(i) == 'K' || text.charAt(i) == 'H' || text.charAt(i) == 'f' || text.charAt(i) == 'J') {
if (isansi) {
isansi = false;
} else {
this.chars += text.charAt(i);
}
} else if (!isansi) {
this.chars += text.charAt(i);
}
}
this.chars = this.chars.replace("\n", "<br>");
}
this.clear = function() {
this.chars = "";
}
this.update = function() {
document.getElementById("terminal-div").innerHTML = this.chars;
}
}
let screen = new TerminalScreen();
socket.on("stdout-packet", packetReceived);
function packetReceived(packet) {
screen.print(packet.rawtext);
screen.update();
}
document.onkeypress = function (e) {
e = e || window.event;
let packet = {
rawtext: String.fromCharCode(e.keyCode)
};
socket.emit("stdin-packet", packet);
};
解决方案
最有可能的是,因为 bash 检测到它没有在伪终端 (pty) 中运行,所以它假定它是以非交互方式运行的。您可以创建一个完整的伪终端(喜欢expect
或ssh
将要做的事情),或者您可以使用-i
标志强制它。
推荐阅读
- google-sheets - 在 Google 表格中输入日期
- python - 如何使用python将excel文件的所有行和列组合成另一个excel文件的单个单元格?
- python - Python Django 数据库事务使用更新
- mysql - SQL 分页尝试:OFFSET(偏移量)在此位置不是有效输入
- linux - ath9k 在 ocb 模式下堆叠日期
- xml - 在 Spring Boot 上接收嵌套的 xml 对象
- ui-automation - 将元素搜索限制为驱动程序 RFT
- c# - SemaphoreSlim 不阻止异步竞争条件
- mongodb - Mongodb 查询查看性能
- javascript - 保存时,Vue 生成错误错误