github.com/walkingsparrow/docker@v1.4.2-0.20151218153551-b708a2249bfa/api/client/exec.go (about) 1 package client 2 3 import ( 4 "fmt" 5 "io" 6 7 "github.com/Sirupsen/logrus" 8 "github.com/docker/docker/api/types" 9 Cli "github.com/docker/docker/cli" 10 "github.com/docker/docker/pkg/promise" 11 "github.com/docker/docker/runconfig" 12 ) 13 14 // CmdExec runs a command in a running container. 15 // 16 // Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...] 17 func (cli *DockerCli) CmdExec(args ...string) error { 18 cmd := Cli.Subcmd("exec", []string{"CONTAINER COMMAND [ARG...]"}, Cli.DockerCommands["exec"].Description, true) 19 20 execConfig, err := runconfig.ParseExec(cmd, args) 21 // just in case the ParseExec does not exit 22 if execConfig.Container == "" || err != nil { 23 return Cli.StatusError{StatusCode: 1} 24 } 25 26 response, err := cli.client.ContainerExecCreate(*execConfig) 27 if err != nil { 28 return err 29 } 30 31 execID := response.ID 32 if execID == "" { 33 fmt.Fprintf(cli.out, "exec ID empty") 34 return nil 35 } 36 37 //Temp struct for execStart so that we don't need to transfer all the execConfig 38 if !execConfig.Detach { 39 if err := cli.CheckTtyInput(execConfig.AttachStdin, execConfig.Tty); err != nil { 40 return err 41 } 42 } else { 43 execStartCheck := types.ExecStartCheck{ 44 Detach: execConfig.Detach, 45 Tty: execConfig.Tty, 46 } 47 48 if err := cli.client.ContainerExecStart(execID, execStartCheck); err != nil { 49 return err 50 } 51 // For now don't print this - wait for when we support exec wait() 52 // fmt.Fprintf(cli.out, "%s\n", execID) 53 return nil 54 } 55 56 // Interactive exec requested. 57 var ( 58 out, stderr io.Writer 59 in io.ReadCloser 60 errCh chan error 61 ) 62 63 if execConfig.AttachStdin { 64 in = cli.in 65 } 66 if execConfig.AttachStdout { 67 out = cli.out 68 } 69 if execConfig.AttachStderr { 70 if execConfig.Tty { 71 stderr = cli.out 72 } else { 73 stderr = cli.err 74 } 75 } 76 77 resp, err := cli.client.ContainerExecAttach(execID, *execConfig) 78 if err != nil { 79 return err 80 } 81 defer resp.Close() 82 errCh = promise.Go(func() error { 83 return cli.holdHijackedConnection(execConfig.Tty, in, out, stderr, resp) 84 }) 85 86 if execConfig.Tty && cli.isTerminalIn { 87 if err := cli.monitorTtySize(execID, true); err != nil { 88 fmt.Fprintf(cli.err, "Error monitoring TTY size: %s\n", err) 89 } 90 } 91 92 if err := <-errCh; err != nil { 93 logrus.Debugf("Error hijack: %s", err) 94 return err 95 } 96 97 var status int 98 if _, status, err = getExecExitCode(cli, execID); err != nil { 99 return err 100 } 101 102 if status != 0 { 103 return Cli.StatusError{StatusCode: status} 104 } 105 106 return nil 107 }