console_unix.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. //go:build linux || darwin || freebsd
  2. package docker
  3. /*
  4. console_unix.go
  5. Real PTY-backed `docker exec -it` for Linux/macOS/FreeBSD hosts using
  6. github.com/creack/pty (MIT). Isolated behind a build tag so non-PTY
  7. platforms (Windows and any other GOOS) compile against console_other.go
  8. instead, per the project's cross-platform rule.
  9. */
  10. import (
  11. "os"
  12. "os/exec"
  13. "github.com/creack/pty"
  14. )
  15. // unixPTY is a ptySession backed by a creack/pty master file.
  16. type unixPTY struct {
  17. ptmx *os.File
  18. cmd *exec.Cmd
  19. }
  20. func (p *unixPTY) Read(b []byte) (int, error) { return p.ptmx.Read(b) }
  21. func (p *unixPTY) Write(b []byte) (int, error) { return p.ptmx.Write(b) }
  22. func (p *unixPTY) Close() error { return p.ptmx.Close() }
  23. func (p *unixPTY) Resize(rows, cols uint16) error {
  24. return pty.Setsize(p.ptmx, &pty.Winsize{Rows: rows, Cols: cols})
  25. }
  26. func (p *unixPTY) Wait() error { return p.cmd.Wait() }
  27. func (p *unixPTY) Kill() {
  28. if p.cmd.Process != nil {
  29. p.cmd.Process.Kill()
  30. }
  31. p.ptmx.Close()
  32. }
  33. // startDockerExecPTY launches `docker exec -it <ref> <shell>` attached to a new
  34. // pseudo-terminal and returns the session.
  35. func startDockerExecPTY(ref, shell string) (ptySession, error) {
  36. cmd := exec.Command("docker", "exec", "-it", ref, shell)
  37. ptmx, err := pty.Start(cmd)
  38. if err != nil {
  39. return nil, err
  40. }
  41. return &unixPTY{ptmx: ptmx, cmd: cmd}, nil
  42. }