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
fix: set stdout in exec when not tty is available #758
base: master
Are you sure you want to change the base?
Conversation
Currently, Exec will force the stdout to the TTY. However, if there's no TTY available, the stdout should be just the program stdout.
Might this also fix an issue I'm seeing using a CLI that uses Bubbletea in a build image (AWS Codebuild). I get:
|
if p.output.TTY() != nil { | ||
c.SetStdout(p.output.TTY()) | ||
} else { | ||
c.SetStdout(p.output) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does setting the output to p.output
differ from the (nil)file returned by p.output.TTY()
?
If the goal is to output to stdout
then would using os.Stdout
work similarly to setting Stderr
below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @hopefulTex!
As background, I'm doing this from a Wish (SSH) application. I debugged Wish, Bubble Tea, and termenv to see where would be the best place for this fix. With this in mind, let me answer your questions.
How does setting the output to
p.output
differ from the (nil)file returned byp.output.TTY()
?
If the output is nil
, the client won't display anything on the screen.
If the goal is to output to
stdout
then would usingos.Stdout
work similarly to settingStderr
below?
I'm afraid the goal is not to output to os.Stdout
. Doing so would show the output of the execution on the server's screen rather than the client's.
The underlying problem is that Bubble Tea's option WithOutput(...)
will convert the output (ssh.Session
which implements the io.Writer
interface) into a termenv.Output
. Then, termenv's output.TTY()
will return nil
as tty
doesn't implement the termenv.File
interface (ssh.Session
doesn't define Fd() uintptr
, which makes sense as it doesn't have a file descriptor).
So, the possible places to fix this issue are:
- Wish's Bubble Tea middleware. Wrap the output in a struct that defines a dummy
FD()
function. But, I would discard this option, as it just instructs to usebubbletea.WithOutput(...)
. - Bubble Tea's WithOutput() option, check if the output is an
ssh.Session
. If so, could you do the wrapping defined in 1? But, it doesn't seem to be the right place as it would add a dependency oncharmbracelet/ssh
. Or, checking if the output is anssh.Session
, and then not creating atermenv.Output
(but it would lose termenv's features). - In termenv's
output.TTY()
, checking iftty
is anssh.Session
. However, it has the same issue as in the previous option. - Finally, the last option I can think of would be to define the dummy
Fd() uintptr
method in (ssh.session
)[https://github.com/charmbracelet/ssh/blob/master/session.go]. To be honest, this would be another option, but I'm torn because defining a dummy file descriptor doesn't sound like a good thing to do.
Yet another option would be to create a Bubble that receives the ssh.Session
(as I wouldn't have access to the program input
/output
as they are not exported). But, the bug would still happen if someone else wants to execute a remote command using a Bubble Tea application with Wish.
I created two sample applications that reproduce the issue. One doesn't allocate a pty, so the command (journalctl -f
) just shows the output to the client. While the other one starts an interactive bash session: https://gist.github.com/ivanvc/cb4580c02e8bb04d17ef286c9183098b
@jonbretman, I think that issue may not be related. Seems like what you're using is not allocating a PTY (or TTY). In my case, the screen gets blank, as the output is
|
Currently, Exec will force the stdout to the TTY. However, if there's no TTY available, the stdout should be just the program stdout.
I found this behavior while using Exec in a Wish application. The application would hang, as
p.output.TTY()
isnil
.