gpt4 book ai didi

go - 使用不带命令的 PTY

转载 作者:行者123 更新时间:2023-12-05 03:22:17 50 4
gpt4 key购买 nike

我打开了一个 issue in creack/pty for this question ,但实际上我认为它可能属于这里,因为它可能更多地与我对库的使用有关,而不是库有任何问题。

我正在使用 websocket api发送 stdin 消息并接收来自命令的 stdout 和 stderr 输出以及退出代码。

例如这个API用在web UI中,发送和接收的消息串如下

此网络用户界面使用 xterm.js提供类似终端的输入用户界面,并将响应(包括 ANSI 转义序列)解释为终端输出。

我正在构建一个终端应用程序,它希望利用相同的 API,因此类似于“终端中的终端”,标准输入被发送到 API,收到的响应在我的应用程序中呈现。

我想使用 creack/pty 作为响应解释器,处理 ANSI 转义序列等,并持有终端 session 的 View ,我可以将其读入字符串并呈现到我的应用程序的屏幕上。

所以流程大致是这样的:

  • stdin 发送到 websocket 连接
  • 收到回复
  • 写回复pty
  • 将整个pty读成字符串
  • 将字符串渲染到屏幕上
  • 重复

如果我以这种方式使用 creack/pty,我实际上没有启动命令 - 它只是一个很好的框,可以为我解释 ansi 转义序列并允许我检索终端的当前“字符串 View ”。

这是我尝试获取一个无命令的 pty、向其写入并从中读取的尝试:

package main

import (
"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.go
panic: write /dev/ptmx: input/output error

goroutine 1 [running]:
main.main()
test.go:52 +0x19c
exit status 2

我正在尝试做的事情是理智的吗?有没有更好的方法来实现我的目标?

最佳答案

我当时正在处理一个类似的问题,而 creack 的 pty 对于您想要的东西来说可能有点过于抽象。我刚刚使用了 golang 标准 xterm 终端模拟器 https://pkg.go.dev/golang.org/x/term和一根 pipe 。

这是我的意思的一个例子的部分片段。您的 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)
}
}()

关于go - 使用不带命令的 PTY,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72765557/

50 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com