Conversation
ax ssh <task> with no command started /bin/sh remotely, but Exec never opened the process's stdin, so the shell read EOF and exited straight away. guest.ExecOptions now takes Stdin, which is streamed to the process via WriteProcessInput and closed on EOF, and Signals, which are delivered with SignalProcess. ax ssh passes os.Stdin and forwards SIGINT, so Ctrl-C interrupts the remote command. When stdin is a terminal the default shell runs as /bin/sh -i so it shows a prompt and survives Ctrl-C. The guest protocol has no PTY support yet, so full-screen programs and job control still don't work. Part of google#374
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #374
ax ssh <task>with no command starts/bin/shin the sandbox, butguest.Client.Execnever opened the process's stdin. The shell read EOF right away and exited, so the command returned without printing anything.The guest protocol in agent-substrate/env already covers this:
StartProcessRequest.stdinopens a stdin pipe,WriteProcessInputstreams into it, andSignalProcesssends a signal to the process group. This PR wires the client up to those calls.Changes
guest.ExecOptionshas two new fields:Stdin io.Readeris streamed to the process throughWriteProcessInput. Remote stdin is closed when the reader hits EOF. A nilStdinkeeps the old behaviour, where the process gets an empty stdin.Signals <-chan os.Signalsends each SIGHUP, SIGINT, SIGQUIT or SIGTERM it receives to the process group throughSignalProcess.ax sshpassesos.Stdinand forwards SIGINT. Ctrl-C now interrupts the remote command instead of killing ax and leaving the remote process running./bin/sh -i. With-iit prints a prompt, and when Ctrl-C reaches the process group it stops the foreground command but not the shell.So
ax ssh task123gives you a working shell: you get a prompt, commands run, Ctrl-C interrupts, Ctrl-D orexitleaves, and the exit status is passed back. Piping also works now, for examplecat script.py | ax ssh task123 -- python3 -.What's still missing
The guest protocol has no PTY. Input is line-buffered by the local terminal, and the remote side has no tty. That means full-screen programs like vim, top and less, job control, and window resizing don't work yet. Supporting them needs a change in agent-substrate/env: a PTY option on
StartProcessRequestand a way to send resizes. I can open an issue there if that sounds right. Once it exists, ax needs to put the local terminal into raw mode and send SIGWINCH sizes, which is a small follow-up.Testing
internal/guest/client_test.gois new. It runs the real guest server from agent-substrate/env on a local port and covers:Stdin, the process still gets an empty stdinFour of these fail on main. The interactive test on main prints just
bye, which is the bug in this issue: the loop sees EOF straight away.I also checked
/bin/sh -iby hand inside Linux containers: dash (the defaultpython:3.12-slimtask image), bash on Ubuntu 22.04, and busybox ash on Alpine. In each one, Ctrl-C duringsleep 30stopped the sleep within a second, and the shell kept accepting commands.go test -race ./...,go vet ./...andmake buildpass, andgo mod tidyleaves go.mod and go.sum unchanged.Notes
ax sshnow forwards stdin for one-off commands as well, which matches whatsshdoes. So a script that runsax sshinside awhile readloop will have the loop's input read by the remote command. If you'd rather only forward stdin for the interactive shell, or add an-nflag like ssh has, I'm happy to change it.