首页 > 解决方案 > 有没有办法从我的 Node.js 生成的 shell 标准输出文本中挽救这些损坏的 bash 转义序列工件?

问题描述

我写了一个类用于生成和与 shell(在 Electron 应用程序中)交互,如下所示:

const { spawn } = require('child_process')
class Shell {
    constructor() {
        this.process = spawn('/bin/bash', []);
        this.process.stdout.on('data', (data) => {
            const out = data.toString()
            console.log('stdout:', out)
            if (this.res) {
                this.res(out)
            }
        });
        this.process.stderr.on('data', function (data) {
            const err = data.toString()
            console.log('stderr:', err)
            if (this.rej) this.rej(err)
        });
    }
    send(command, throwErr = false) {
        return new Promise((resolve, reject) => {
            this.res = resolve
            if (throwErr) this.rej = reject
            else this.rej = resolve
            this.process.stdin.write(command + '\n')
        })
    }
}

我得到的输出是这样的:

stdout: ]0;student@linux-opstation-jyrf: ~[01;32mstudent@linux-opstation-jyrf[00m:[01;34m~[00m$

这是我使用 JSON 对输出进行字符串化以查看转义字符的版本:stdout: "\u001b]0;student@linux-opstation-jyrf: ~\u0007\u001b[01;32mstudent@linux-opstation-jyrf\u001b[00m:\u001b[01;34m~\u001b[00m$ ssh -t -t -oStrictHostKeyChecking=no student@10.5\r50.30.231\r\n"

我意识到这些是用于格式化的 bash 转义序列中的伪影,我无法弄清楚如何摆脱它,特别是因为没有打印转义字符。

编辑:所以我将原始标准输出Bufferdata在代码中)写入二进制文件:

fs.createWriteStream(path, { encoding: 'binary'}).write(data);

并发现该方法似乎没有发生任何损失.toString()(我认为?)所以我只好挠头,其余的标准输出标记被截断。

00000000: 1b5d 303b 7374 7564 656e 7440 6c69 6e75  .]0;student@linu
00000010: 782d 6f70 7374 6174 696f 6e2d 6a79 7266  x-opstation-jyrf
00000020: 3a20 7e07 1b5b 3031 3b33 326d 7374 7564  : ~..[01;32mstud
00000030: 656e 7440 6c69 6e75 782d 6f70 7374 6174  ent@linux-opstat
00000040: 696f 6e2d 6a79 7266 1b5b 3030 6d3a 1b5b  ion-jyrf.[00m:.[
00000050: 3031 3b33 346d 7e1b 5b30 306d 2420 7373  01;34m~.[00m$ ss
00000060: 6820 2d74 202d 7420 2d6f 5374 7269 6374  h -t -t -oStrict
00000070: 486f 7374 4b65 7943 6865 636b 696e 673d  HostKeyChecking=
00000080: 6e6f 2073 7475 6465 6e74 4031 302e 350d  no student@10.5.
00000090: 3530 2e33 302e 3233 310d 0a              50.30.231..

但也许我在保存文件时没有正确编码,因为我认为原始缓冲区应该(?)输出这样的文本\u001b[00m:\u001b[01;34m并且\uFFFF十六进制字符不存在。编辑:啊,\uFFFF显然是unicode。仍在弄清楚如何将该缓冲区正确保存为二进制文件,我认为使用{encoding: 'binary'}set 作为选项会丢失 unicode。否则十六进制转储只显示 utf8,这听起来更有可能。

标签: node.jsbashelectron

解决方案


假设这些工件确实来自定制的提示字符串,最简单的做法是更改提示字符串。有多种替代方法,这在某种程度上取决于提示字符串的设置位置。

如果您得到提示,则bash作为交互式 shell 运行。它不会使用您用来启动它的命令作为登录 shell 运行。因此,相关的初始化步骤如下:

当一个不是登录 shell 的交互式 shell 启动时,bash 读取并执行来自~/.bashrc的命令(如果该文件存在)。这可以通过使用--norc选项来禁止。--rcfile 选项将file强制bash从 file 而不是 ~/.bashrc.

Bash 手册页

因此,您可以通过--norc选项来bash禁止读取任何 shell 初始化文件,从而获得默认提示(以及其他所有内容)。但是那个环境可能对您的需求来说太稀疏了,因此作为替代方案,您可以创建一个专用的 shell 配置文件来设置您想要的确切配置,并使用该--rcfile选项使bash您的程序启动的实例使用它。 这可能是您最好的选择,但可能需要一些工作才能根据需要进行设置。

作为一种更快更脏的替代方法,您可以修改相关~/.bashrc以更改提示字符串(删除 and 的定义PS1PS2或者将它们重新定义为默认值:)PS1='\s-\v\$ ' PS2='> '。您还可以将前两个与自定义配置文件结合起来,该文件读取默认配置文件并覆盖提示字符串:

电子.bashrc

. ~/.bashrc
PS1='\s-\v\$ '
PS2='> '

推荐阅读