【发布时间】:2015-05-09 09:26:34
【问题描述】:
我正在编写一个 Go 程序,它将使用本机 x/crypto/ssh 库通过 SSH 连接到主机并删除一个交互式 shell。
我正在使用RequestPty(),但远程端的 (bash) shell 与控制代码的行为不符。
当我输入各种控制字符时,它们会被我的终端回显:
$ ^[[A
字符仍然工作,如果我在按下向上箭头后按下回车,前一个命令就会运行——但是控制字符输出会破坏应该在那里显示的内容。选项卡也是如此。
有没有一些简单的方法可以让它工作?当我过去实现类似的系统时,这不是问题,因为我刚刚向openssh 支付了费用,并且进程组的语义将其全部整理出来。
我已经研究过“The TTY Demystified”,尽管它很棒,但不清楚从哪里开始。
我想调查的几件事:
- enable raw mode in my terminal - 但我不想在不理解原因的情况下这样做,而且它似乎做正确的事
- fiddle with the terminal mode flags
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-256color 和 vt100。
记录一下 - 在实际代码中,我有一个 for/select 循环来捕获进程的各种信号并将它们发送到 Session,而不仅仅是调用 session.Wait()。
【问题讨论】:
-
你试过禁用
ECHOCTL终端模式吗? -
@EmilDavtyan 修复了它!现在明白为什么了。
-
@Cerales 请记住回答您自己的问题并接受答案:)
-
@Cerales 我将我的评论作为答案发布,因此您可以将其标记为已回答。
-
@Cera:
for/select你在等待什么信号?当你得到它们时,你对它们做了什么?我似乎无法让SIGINT(CTRL+C) 以我期望的方式工作。