attach.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. defer stream.Close()
  29. var c types.ContainerJSON
  30. if err := json.NewDecoder(stream).Decode(&c); err != nil {
  31. return err
  32. }
  33. if !c.State.Running {
  34. return fmt.Errorf("You cannot attach to a stopped container, start it first")
  35. }
  36. if err := cli.CheckTtyInput(!*noStdin, c.Config.Tty); err != nil {
  37. return err
  38. }
  39. if c.Config.Tty && cli.isTerminalOut {
  40. if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
  41. logrus.Debugf("Error monitoring TTY size: %s", err)
  42. }
  43. }
  44. var in io.ReadCloser
  45. v := url.Values{}
  46. v.Set("stream", "1")
  47. if !*noStdin && c.Config.OpenStdin {
  48. v.Set("stdin", "1")
  49. in = cli.in
  50. }
  51. v.Set("stdout", "1")
  52. v.Set("stderr", "1")
  53. if *proxy && !c.Config.Tty {
  54. sigc := cli.forwardAllSignals(cmd.Arg(0))
  55. defer signal.StopCatch(sigc)
  56. }
  57. if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), c.Config.Tty, in, cli.out, cli.err, nil, nil); err != nil {
  58. return err
  59. }
  60. _, status, err := getExitCode(cli, cmd.Arg(0))
  61. if err != nil {
  62. return err
  63. }
  64. if status != 0 {
  65. return StatusError{StatusCode: status}
  66. }
  67. return nil
  68. }