为了账号安全,请及时绑定邮箱和手机立即绑定

使用不带命令的 PTY

使用不带命令的 PTY

Go
小唯快跑啊 2022-12-26 16:37:46
我在 creack/pty 中为这个问题打开了一个问题,但实际上我认为它可能属于这里,因为它可能更多地与我对库的使用有关,而不是库的任何问题。我正在使用一个websocket api,它发送 stdin 消息并从命令接收 stdout 和 stderr 输出以及退出代码。比如这个API用在web UI中,发送和接收的消息串如下此 Web UI 使用xterm.js提供类似终端的输入 ui,并将响应(包括 ansi 转义序列)解释为终端输出。我正在构建一个终端应用程序,它希望利用相同的 API,因此类似于“终端中的终端”,其中将标准输入发送到 API,并在我的应用程序中呈现接收到的响应。我想使用 creack/pty 作为响应解释器,处理 ansi 转义序列等,并持有终端会话的视图,我可以将其读入字符串并呈现到我的应用程序的屏幕上。所以流程大致是这样的:stdin 发送到 websocket 连接收到回复写对 pty 的回应读取整个 pty 到字符串将字符串渲染到屏幕重复如果我以这种方式使用 creack/pty,我实际上没有启动命令 - 它只是一个很好的框,可以为我解释 ansi 转义序列并允许我检索终端的当前“字符串视图”。这是我尝试获取无命令 pty、写入并从中读取的尝试:package mainimport (    "bytes"    "fmt"    "github.com/creack/pty"    "io"    "os")func getPtyWithoutCommand() (*os.File, error) {    // this function just pty.StartWithAttrs with command-specific stuff commented out    pty, tty, err := pty.Open()    if err != nil {        return nil, err    }    defer func() { _ = tty.Close() }() // Best effort.    // if sz != nil {    //  if err := Setsize(pty, sz); err != nil {    //      _ = pty.Close() // Best effort.    //      return nil, err    //  }    // }    // if c.Stdout == nil {    //  c.Stdout = tty    // }    // if c.Stderr == nil {    //  c.Stderr = tty    // }    // if c.Stdin == nil {    //  c.Stdin = tty    // }    //    // c.SysProcAttr = attrs    //    // if err := c.Start(); err != nil {    //  _ = pty.Close() // Best effort.    //  return nil, err    // }    return pty, err}func main() {    myPty, err := getPtyWithoutCommand()    if err != nil {        panic(err)    }    _, err = myPty.Write([]byte("test\n"))    if err != nil {        panic(err)    }    _, err = myPty.Write([]byte{4}) // EOT    if err != nil {        panic(err)    }    buf := new(bytes.Buffer)    _, err = io.Copy(buf, myPty)    if err != nil {        panic(err)    }    fmt.Println(buf.String())}我收到以下错误❯ go run test.gopanic: write /dev/ptmx: input/output errorgoroutine 1 [running]:main.main()        test.go:52 +0x19cexit status 2我正在努力做的事情是理智的吗?有没有更好的方法来实现我的目标?
查看完整描述

1 回答

?
隔江千里

TA贡献1906条经验 获得超10个赞

我正在处理一个类似的问题,而 creack 的 pty 可能对于你想要的东西来说有点太抽象了。我刚刚使用了 golang 标准 xterm 终端仿真器https://pkg.go.dev/golang.org/x/term和一个管道。


这是我的意思的一个例子的部分片段。您的 stdin 流被送入stdin_writer并且您的 stdout 被写入writer,不要忘记Flush()!


stdin_reader, stdin_writer := io.Pipe()

reader := bufio.NewReader(stdin_reader)


stdout_writer := bytes.Buffer{}

writer := bufio.NewWriter(&stdout_writer)


rw := bufio.NewReadWriter(reader, writer)

t := term.NewTerminal(rw, prompt)


// constantly be reading lines

go func() {

    for {

        line, err := t.ReadLine()

        if err == io.EOF {

            log.Printf("got EOF")

        }

        if err != nil {

            log.Printf("got err")

        }

        if line == "" {

            continue

        }

        log.Printf("LINE: %s", line)

    }

}()


查看完整回答
反对 回复 2022-12-26
  • 1 回答
  • 0 关注
  • 84 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信