节点.js子进程不会接收标准,除非我关闭标准输入流



我正在构建一个将泰拉瑞亚服务器包装在节点中的不和谐机器人.js以便服务器用户可以重新启动服务器和类似的操作。 我已经设法完成了一半的工作,但我似乎无法创建命令来在泰拉瑞亚服务器上执行命令。 我已经将其设置为将命令写入子进程的 stdin,并且一些基本的调试验证了它是否确实如此,但显然没有任何反应。

在子进程 stdin的 Node.js 文档中,它说">请注意,如果子进程等待读取其所有输入,则子进程将不会继续,直到通过 end(( 关闭此流。 这似乎是问题所在,因为在其上调用 end(( 函数实际上确实按预期发送命令。 也就是说,似乎很难相信我无法在不关闭 stdin 的情况下连续向 stdin 发送命令。

这真的是问题所在吗,如果是,我有什么办法来解决它? 我的代码可以在下面找到。

const discordjs = require("discord.js");
const child_process = require("child_process");
const tokens = require("./tokens");
const client = new discordjs.Client();

const terrariaServerPath = "C:\Program Files (x86)\Steam\steamapps\common\Terraria\TerrariaServer.exe"
const terrariaArgs = ['-port', '7777', "-maxplayers", "8", "-world", "test.wld"]
var child = child_process.spawn(terrariaServerPath, terrariaArgs);
client.on('ready', () => {
    console.log(`Logged in as ${client.user.tag}!`);
});
client.on('disconnect', () => {
    client.destroy();
});
client.on('message', msg => {
    if (msg.channel.name === 'terraria') {
        var msgSplit = msg.content.split(" ");
        if (msgSplit[0] === "!restart") {
            child.kill();
            child = child_process.spawn(terrariaServerPath, terrariaArgs);
            registerStdio();
            msg.reply("restarting server")
        }
        if (msgSplit[0] === "!exec") {
            msg.reply(msgSplit[1]);
            child.stdin.write(msgSplit[1] + "n");
            child.stdin.end();
        }
    }
});
client.login(tokens.discord_token);
var registerStdio = function () {
    child.stdout.on('data', (data) => {
        console.log(`${data}`);
    });
    child.stderr.on('data', (data) => {
        console.error(`${data}`);
    });
}
registerStdio();

我能够通过使用库节点pty来解决问题。 据我所知,问题是子进程没有读取 stdin 本身,我无法刷新它。 Node-pty 创建一个虚拟终端对象,可以写入该对象而不是 stdin。 此对象不缓冲写入,因此任何输入都会立即发送到程序。

最新更新