Я пишу программу Go, которая будет подключаться к хосту через SSH, используя собственную библиотеку x/crypto/ssh и отбрасывать оболочку.Как я могу отправить управляющие последовательности терминала через SSH с Go?
Я использую RequestPty()
, но оболочка (bash) на удаленном конце работает не так, как ожидалось, с помощью управляющих кодов.
Когда вводить различные управляющие символы, они возвращаются назад на моем терминале:
$ ^[[A
персонажей еще работы в том смысле, что, если нажать клавишу ВВОД после нажатия на стрелку вверх, предыдущая команда запускается - но вывод управляющего символа сжимает то, что должно отображаться там. То же самое касается вкладки.
Есть ли какой-нибудь простой способ заставить это работать? Когда я реализовал подобные системы в прошлом, это не было проблемой, потому что я только что обрезал до openssh
, и семантика групп процессов разобрала все это.
Я изучил «The TTY Demystified» и так хорошо, как не ясно, с чего начать.
Несколько вещей, которые я думал исследовать:
- enable raw mode in my terminal - но я не хочу, чтобы сделать это, не понимая, почему, и это, кажется, не сделать правильную вещь
- fiddle with the terminal mode flags
openssh
сам по себе должен делать эту работу правильно, но это настоящий лучший из кодовой базы для изучения.
На самом деле мне не ясно, выполняется ли эта печать моим локальным эмулятором терминала или оболочкой или кодом на удаленном хосте.
С чего начать?
Вот пример моего кода:
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
.
Для записи - в реальном коде, а не только призыв к session.Wait()
, у меня есть for/select
цикл, который улавливает различные сигналы процесса и отправляет их на к Session
.
Вы пытались отключить режим терминала ECHOCTL? –
@ EmilDavtyan, который исправил это! Теперь, чтобы понять, почему. – Cera
@Cerales Пожалуйста, не забудьте ответить на свой вопрос и принять ответ :) – user918176