我在 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 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
我正在努力做的事情是理智的吗?有没有更好的方法来实现我的目标?
隔江千里
相关分类