Go 从伪终端获取上一个输入
我有一个用来创建伪终端的程序。它的工作原理是我给出了一个命令——在本例中是Go 从伪终端获取上一个输入,go,unix,terminal,pty,terminal-emulator,Go,Unix,Terminal,Pty,Terminal Emulator,我有一个用来创建伪终端的程序。它的工作原理是我给出了一个命令——在本例中是bash-I——它创建了一个文件对象,您可以在其中读写,它将作为stdin和stdout,我不断地读取文件并将数据发送到客户端。这很好,但当另一个客户端连接时,它只会在她连接后接收数据,这是不可取的 正常客户端行为: computer:~$ computer:~$ computer:~$ computer:~$ computer:~$ echo "a" a computer:~$ 第二个客户端在客户端1键入c后连接:
bash-I
——它创建了一个文件对象,您可以在其中读写,它将作为stdin
和stdout
,我不断地读取文件并将数据发送到客户端。这很好,但当另一个客户端连接时,它只会在她连接后接收数据,这是不可取的
正常客户端行为:
computer:~$
computer:~$
computer:~$
computer:~$
computer:~$ echo "a"
a
computer:~$
第二个客户端在客户端1键入c后连接:
ho "a"
a
computer:~$
正如您所看到的,这是有问题的,因为客户端2将有截断的输入,期望的行为是发送所有历史记录或缓存状态
我尝试使用file.ReadAt(b,0)
读取文件,从偏移量0开始读取文件,并将结果存储在b
中,但我得到ENXIO:6-没有这样的设备或地址
我认为发生这种情况是因为文件不是真正的文件。我目前正在做的是将所有输出数据存储到一个缓冲区中,当一个新客户端连接时,我会发送存储的缓冲区,但这不是一个完整的解决方案,因为如果客户端使用clear
,或者如果它使用了一个与终端混乱的命令,比如vi
或nano
,缓冲区不会自适应,它只会存储数据输出
我用的是围棋,但我认为这个问题与一种特定的语言没有太大的关系,所以如果你有C语言或其他语言的答案,我可以看到它,并尝试在围棋中找到对应的答案。无论如何,这是我正在使用的GO代码
初始化:
c := exec.Command("bash", "-i")
// Start the command with a pty.
ptmx, err := pty.Start(c) // ptmx is of type *os.File
阅读:
// this gets called in a while true loop
func (t *Terminal) Read(b []byte) (int, error) {
n, e := t.ptmx.Read(b)
for _, byt := range b {
t.buffer.Insert(byt)
}
return n, e
}
补偿对你没有帮助。问题在于,pty是一种类似通道的设备,没有内存:一旦数据通过pty从一端流向另一端,并被读卡器消耗,这些数据就会消失。操作系统的寻道偏移量不相关 如果您想维护所有交换数据的日志,您必须自己维护