Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

golang/x/term Terminals do not work when SSH command is provided #235

Closed
MexHigh opened this issue Aug 23, 2024 · 3 comments
Closed

golang/x/term Terminals do not work when SSH command is provided #235

MexHigh opened this issue Aug 23, 2024 · 3 comments

Comments

@MexHigh
Copy link

MexHigh commented Aug 23, 2024

I'm trying to build a little terminal application with golang.org/x/term. Until now I only had one terminal which was started when I ran ssh user@localhost. But if SSH is given a command while starting the connection, the terminals no longer work (terminal.ReadLine() and .ReadPassword("...") never return and don't react to newlines).

This is a minimal example to reproduce this:

package main

import (
	"io"

	"github.com/gliderlabs/ssh"
	"golang.org/x/term"
)

func main() {
	handler := func(s ssh.Session) {
		term := term.NewTerminal(s, "Enter your name: ")
		line, err := term.ReadLine()
		if err != nil {
			panic(err)
		}
		io.WriteString(s, "Your name is: "+line+"\n")
	}

	server := ssh.Server{
		Addr:    ":2222",
		Handler: handler,
	}
	server.SetOption(ssh.HostKeyFile("./id_ed25519"))
	panic(server.ListenAndServe())
}

When I run ssh user@localhost -p 2222, it works:

image

But when a append any command to SSH nothing happens at ReadLine(), no matter how often I press Enter: However, my input is somehow "reflected" into the SSH window, which is not the case without the command (maybe this is the reason, why ReadLine() never returns?):

image


This is my go.mod if required:

module my-turn

go 1.20

require (
	github.com/gliderlabs/ssh v0.3.7
	golang.org/x/term v0.23.0
)

require (
	github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
	golang.org/x/crypto v0.26.0 // indirect
	golang.org/x/sys v0.24.0 // indirect
)

I tried debugging this for some time now, but I don't get why this is not working. Any ideas how to fix this? Or is this a bug?

@MexHigh
Copy link
Author

MexHigh commented Aug 23, 2024

Just found out that it works with ssh user@localhost -tt -p 2222 some-command. Is there any way to accomplish this in the backend implementation? Or is this a limitation of the SSH client?

@smlx
Copy link

smlx commented Aug 23, 2024

As per the ssh man page, a pty will only be requested for an interactive session by default. When a command is supplied, it is executed in a non-interactive session.

A pty has a client and a server side, so both your client needs to request the pty and the server needs to accept the request (this library does by default). So no, there is no way for a server to force a client to use a pty.

This video might help visualise exactly what is being emulated by the pty.

@MexHigh
Copy link
Author

MexHigh commented Aug 24, 2024

Ok that makes sense. Thanks for the explaination!

@MexHigh MexHigh closed this as completed Aug 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants