attach.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package client
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io"
  6. "net/url"
  7. "github.com/Sirupsen/logrus"
  8. "github.com/docker/docker/api/types"
  9. flag "github.com/docker/docker/pkg/mflag"
  10. "github.com/docker/docker/pkg/signal"
  11. )
  12. // CmdAttach attaches to a running container.
  13. //
  14. // Usage: docker attach [OPTIONS] CONTAINER
  15. func (cli *DockerCli) CmdAttach(args ...string) error {
  16. var (
  17. cmd = cli.Subcmd("attach", []string{"CONTAINER"}, "Attach to a running container", true)
  18. noStdin = cmd.Bool([]string{"#nostdin", "-no-stdin"}, false, "Do not attach STDIN")
  19. proxy = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxy all received signals to the process")
  20. )
  21. cmd.Require(flag.Exact, 1)
  22. cmd.ParseFlags(args, true)
  23. name := cmd.Arg(0)
  24. stream, _, _, err := cli.call("GET", "/containers/"+name+"/json", nil, nil)
  25. if err != nil {
  26. return err
  27. }
  28. var c types.ContainerJSON
  29. if err := json.NewDecoder(stream).Decode(&c); err != nil {
  30. return err
  31. }
  32. if !c.State.Running {
  33. return fmt.Errorf("You cannot attach to a stopped container, start it first")
  34. }
  35. if err := cli.CheckTtyInput(!*noStdin, c.Config.Tty); err != nil {
  36. return err
  37. }
  38. if c.Config.Tty && cli.isTerminalOut {
  39. if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
  40. logrus.Debugf("Error monitoring TTY size: %s", err)
  41. }
  42. }
  43. var in io.ReadCloser
  44. v := url.Values{}
  45. v.Set("stream", "1")
  46. if !*noStdin && c.Config.OpenStdin {
  47. v.Set("stdin", "1")
  48. in = cli.in
  49. }
  50. v.Set("stdout", "1")
  51. v.Set("stderr", "1")
  52. if *proxy && !c.Config.Tty {
  53. sigc := cli.forwardAllSignals(cmd.Arg(0))
  54. defer signal.StopCatch(sigc)
  55. }
  56. if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), c.Config.Tty, in, cli.out, cli.err, nil, nil); err != nil {
  57. return err
  58. }
  59. _, status, err := getExitCode(cli, cmd.Arg(0))
  60. if err != nil {
  61. return err
  62. }
  63. if status != 0 {
  64. return StatusError{StatusCode: status}
  65. }
  66. return nil
  67. }