ssh: say why when there is no shell to run
The published container image has no shell, so a session used to end at once with nothing printed for a command. It now explains that, and what to do about it, and exits with status 127. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a2403ecf9d
commit
79bd4d8646
2 files changed
+37
No files matched your search
@@ -25,6 +25,14 @@ func run(ch ssh.Channel, cmd string, p *ptyReq, win <-chan [2]uint32) int {
|
|||||||
if shell == "" {
|
if shell == "" {
|
||||||
shell = "/bin/sh"
|
shell = "/bin/sh"
|
||||||
}
|
}
|
||||||
|
// Without this the client sees only a session that ends at once. The container image Bamboo is
|
||||||
|
// published in contains no shell at all, so say so, and what to do about it.
|
||||||
|
if _, err := exec.LookPath(shell); err != nil {
|
||||||
|
fmt.Fprintf(ch.Stderr(), "bamboo: there is no shell to run (%v).\r\n"+
|
||||||
|
"The Bamboo container image has none, and a shell in a container is not a shell on the machine. "+
|
||||||
|
"Run Bamboo directly on the machine (for example with its systemd unit) to get one, or set SHELL to a shell that exists.\r\n", err)
|
||||||
|
return 127
|
||||||
|
}
|
||||||
var c *exec.Cmd
|
var c *exec.Cmd
|
||||||
if cmd == "" {
|
if cmd == "" {
|
||||||
c = exec.Command(shell, "-l")
|
c = exec.Command(shell, "-l")
|
||||||
|
|||||||
@@ -82,3 +82,32 @@ func TestShell(t *testing.T) {
|
|||||||
t.Fatalf("got %q, %v", out.String(), err)
|
t.Fatalf("got %q, %v", out.String(), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A machine with no shell (the published container image is one) must say so, not just hang up.
|
||||||
|
func TestNoShellIsExplained(t *testing.T) {
|
||||||
|
t.Setenv("SHELL", "/nonexistent/shell")
|
||||||
|
for name, usePty := range map[string]bool{"exec": false, "pty shell": true} {
|
||||||
|
s, done := session(t)
|
||||||
|
var stderr, stdout strings.Builder
|
||||||
|
s.Stderr, s.Stdout = &stderr, &stdout
|
||||||
|
var err error
|
||||||
|
if usePty {
|
||||||
|
if err = s.RequestPty("xterm", 24, 80, ssh.TerminalModes{}); err == nil {
|
||||||
|
err = s.Shell()
|
||||||
|
if err == nil {
|
||||||
|
err = s.Wait()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = s.Run("true")
|
||||||
|
}
|
||||||
|
done()
|
||||||
|
var ee *ssh.ExitError
|
||||||
|
if !errors.As(err, &ee) || ee.ExitStatus() != 127 {
|
||||||
|
t.Errorf("%s: want exit status 127, got %v", name, err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(stderr.String()+stdout.String(), "no shell to run") {
|
||||||
|
t.Errorf("%s: no explanation (stderr %q, stdout %q)", name, stderr.String(), stdout.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user