Ich schreibe ein Go-Programm, das über die native x/crypto/ssh-Bibliothek eine Verbindung zu einem Host über SSH herstellt und eine interaktive Shell ablegt.Wie kann ich terminale Escape-Sequenzen über SSH mit Go senden?
Ich verwende RequestPty()
, aber die (Bash) Shell auf dem Remote-Ende verhält sich nicht wie erwartet mit Steuercodes.
Wenn ich verschiedene Steuerzeichen eingeben, werden sie wieder von meinem Terminal hallte:
$ ^[[A
Die Zeichen, die noch Arbeit im Sinn, wenn ich drücken Sie nach dem Pfeil nach oben drücken, der vorherige Befehl wird ausgeführt - aber die Steuerzeichenausgabe übertrumpft was dort angezeigt werden soll. Das gleiche gilt für Tab.
Gibt es einen einfachen Weg, dies zum Laufen zu bringen? Wenn ich in der Vergangenheit ähnliche Systeme implementiert habe, war das kein Problem, denn ich habe gerade auf openssh
geschossen, und die Semantik der Prozessgruppen sortiert alles aus.
Ich habe studiert "The TTY Demystified" und so gut wie es ist, ist es nicht klar, wo ich anfangen soll.
Ein paar Dinge, die ich gedacht habe, zu untersuchen:
- enable raw mode in my terminal - aber ich will nicht, dies zu tun, ohne zu verstehen, warum, und es scheint nicht, das Richtige zu tun
- fiddle with the terminal mode flags
openssh
selbst muss diese Arbeit richtig tun, aber es ist ein echter beste aus einer Code-Basis zu untersuchen.
Es ist mir nicht wirklich klar, ob dieser Druck von meinem lokalen Terminal-Emulator oder Shell oder vom Code auf dem Remote-Host ausgeführt wird.
Wo fange ich an?
Hier ist ein Beispiel von meinem Code:
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()
ich dies mit Zeitwerte versucht haben, andere als xterm
: screen-256color
und vt100
.
Für das Protokoll - in der realen Code, anstatt nur einen Aufruf session.Wait()
, habe ich eine for/select
Schleife, die verschiedene Signale an den Prozess fängt und sendet sie an den Session
auf.
Haben Sie versucht, den ECHOCTL-Terminalmodus zu deaktivieren? –
@EmilDavtyan, die es behoben! Jetzt zu verstehen, warum. – Cera
@Cerales Bitte denken Sie daran, Ihre eigene Frage zu beantworten und die Antwort zu akzeptieren :) – user918176