除非我关闭stdin流,否则Node.js子进程不接收stdin

时间:2018-01-11 17:03:44

标签: node.js stdin child-process

我正在构建一个在node.js中包装terraria服务器的discord bot,以便服务器用户可以重启服务器和类似的操作。我已经设法完成了一半的工作,但我似乎无法创建一个命令来在terraria服务器上执行命令。我已经将它设置为将命令写入子进程的stdin,并且一些基本的调试验证它确实存在,但是没有任何事情发生。

在子进程stdin的Node.js文档中,它表示" 请注意,如果子进程等待读取其所有输入,则子进程将不会继续,直到此流已通过end关闭()&#34。这看起来很可能是问题,因为调用它上面的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();

1 个答案:

答案 0 :(得分:1)

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