gpt4 book ai didi

bash - 如何使用 Go 通过 SSH 发送终端转义序列?

转载 作者:IT老高 更新时间:2023-10-28 13:10:44 25 4
gpt4 key购买 nike

我正在编写一个 Go 程序,它将使用 native x/crypto/ssh 通过 SSH 连接到主机库并删除一个交互式外壳。

我正在使用 RequestPty() ,但远程端的 (bash) shell 与控制代码的行为不符。

当我输入各种控制字符时,它们会被我的终端回显:

$ ^[[A

字符仍然工作,如果我在按向上箭头后按回车键,就会运行上一个命令 - 但控制字符输出会破坏应该在那里显示的内容。选项卡也是如此。

有没有一些简单的方法可以让它工作?当我过去实现类似的系统时,这不是问题,因为我只是使用 openssh,进程组的语义将其全部整理出来。

我已经研究了“The TTY Demystified”,尽管它非常好,但不清楚从哪里开始。

我想调查的几件事:

openssh 本身必须正确地完成这项工作,但它是一个真正值得研究的最佳代码库。

我并不清楚这个打印是由我的本地终端仿真器或 shell 完成的,还是由远程主机上的代码完成的。

我从哪里开始?


这是我的代码示例:

conf := ssh.ClientConfig{
User: myuser,
Auth: []ssh.AuthMethod{ssh.Password(my_password)}
}
conn, err := ssh.Dial("tcp", myhost, conf)
if err != nil {
return err
}
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
return err
}
defer session.Close()
session.Stdout = os.Stdout
session.Stderr = os.Stderr
session.Stdin = os.Stdin

modes := ssh.TerminalModes{
ssh.ECHO: 0
ssh.TTY_OP_ISPEED: 14400,
ssh.TTY_OP_OSPEED: 14400
}
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
return err
}
if err = session.Shell(); err != nil {
return err
}

return session.Wait()

我已经尝试过使用 xterm 以外的术语值:screen-256colorvt100

记录一下 - 在实际代码中,我有一个 for/select 循环来捕获各种信号,而不仅仅是对 session.Wait() 的调用进程并将它们发送到 Session

最佳答案

ssh.ECHO: 0ssh.ECHOCTL: 0 设置对我不起作用。对于遇到此问题的其他人,以下是使用 Go ssh 库获得完全工作的交互式终端所需的粗略代码:

config := return &ssh.ClientConfig{
User: "username",
Auth: []ssh.AuthMethod{ssh.Password("password")},
}

client, err := ssh.Dial("tcp", "12.34.56.78:22", config)
if err != nil { ... }
defer client.Close()

session, err := client.NewSession()
if err != nil { ... }
defer session.Close()

session.Stdout = os.Stdout
session.Stderr = os.Stderr
session.Stdin = os.Stdin

modes := ssh.TerminalModes{
ssh.ECHO: 1, // enable echoing
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}

fileDescriptor := int(os.Stdin.Fd())

if terminal.IsTerminal(fileDescriptor) {
originalState, err := terminal.MakeRaw(fileDescriptor)
if err != nil { ... }
defer terminal.Restore(fileDescriptor, originalState)

termWidth, termHeight, err := terminal.GetSize(fileDescriptor)
if err != nil { ... }

err = session.RequestPty("xterm-256color", termHeight, termWidth, modes)
if err != nil { ... }
}

err = session.Shell()
if err != nil { ... }

// You should now be connected via SSH with a fully-interactive terminal
// This call blocks until the user exits the session (e.g. via CTRL + D)
session.Wait()

请注意,所有键盘功能(制表符补全、向上箭头)和信号处理(CTRL + CCTRL + D)在上述设置下都能正常工作。

关于bash - 如何使用 Go 通过 SSH 发送终端转义序列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28921409/

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