1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

docker run [-a [stdin|stdout|stderr] [...]]: choose which streams to attach to when running a command. Fixes #234.

This commit is contained in:
Solomon Hykes 2013-04-02 18:07:16 -07:00
parent c77063afcd
commit c04af2a330
2 changed files with 87 additions and 40 deletions

View file

@ -827,6 +827,33 @@ func (opts *ListOpts) Set(value string) error {
return nil
}
// AttachOpts stores arguments to 'docker run -a', eg. which streams to attach to
type AttachOpts map[string]bool
func NewAttachOpts() *AttachOpts {
opts := make(map[string]bool)
return (*AttachOpts)(&opts)
}
func (opts *AttachOpts) String() string {
return fmt.Sprint(*opts)
}
func (opts *AttachOpts) Set(val string) error {
if val != "stdin" && val != "stdout" && val != "stderr" {
return fmt.Errorf("Unsupported stream name: %s", val)
}
(*opts)[val] = true
return nil
}
func (opts *AttachOpts) Get(val string) bool {
if res, exists := (*opts)[val]; exists {
return res
}
return false
}
func (srv *Server) CmdTag(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "tag", "[OPTIONS] IMAGE REPOSITORY [TAG]", "Tag an image into a repository")
force := cmd.Bool("f", false, "Force")
@ -870,29 +897,30 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string)
return err
}
}
// Run the container
if !config.Detach {
var attachErr chan error
if config.OpenStdin {
Debugf("Attaching with stdin\n")
attachErr = container.Attach(stdin, stdout, stdout)
} else {
Debugf("Attaching without stdin\n")
attachErr = container.Attach(nil, stdout, nil)
var (
cStdin io.Reader
cStdout, cStderr io.Writer
)
if config.AttachStdin {
cStdin = stdin
}
if config.AttachStdout {
cStdout = stdout
}
if config.AttachStderr {
cStderr = stdout // FIXME: rcli can't differentiate stdout from stderr
}
attachErr := container.Attach(cStdin, cStdout, cStderr)
Debugf("Starting\n")
if err := container.Start(); err != nil {
return err
}
if cStdout == nil && cStderr == nil {
fmt.Fprintln(stdout, container.ShortId())
}
Debugf("Waiting for attach to return\n")
return <-attachErr
}
if err := container.Start(); err != nil {
return err
}
fmt.Fprintln(stdout, container.ShortId())
return nil
}
func NewServer() (*Server, error) {
if runtime.GOARCH != "amd64" {

View file

@ -52,7 +52,9 @@ type Config struct {
User string
Memory int64 // Memory limit (in bytes)
MemorySwap int64 // Total memory usage (memory + swap); set `-1' to disable swap
Detach bool
AttachStdin bool
AttachStdout bool
AttachStderr bool
Ports []int
Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
OpenStdin bool // Open stdin
@ -70,6 +72,8 @@ func ParseRun(args []string, stdout io.Writer) (*Config, error) {
flUser := cmd.String("u", "", "Username or UID")
flDetach := cmd.Bool("d", false, "Detached mode: leave the container running in the background")
flAttach := NewAttachOpts()
cmd.Var(flAttach, "a", "Attach to stdin, stdout or stderr.")
flStdin := cmd.Bool("i", false, "Keep stdin open even if not attached")
flTty := cmd.Bool("t", false, "Allocate a pseudo-tty")
flMemory := cmd.Int64("m", 0, "Memory limit (in bytes)")
@ -81,6 +85,19 @@ func ParseRun(args []string, stdout io.Writer) (*Config, error) {
if err := cmd.Parse(args); err != nil {
return nil, err
}
if *flDetach && len(*flAttach) > 0 {
return nil, fmt.Errorf("Conflicting options: -a and -d")
}
// If neither -d or -a are set, attach to everything by default
if len(*flAttach) == 0 && !*flDetach {
if !*flDetach {
flAttach.Set("stdout")
flAttach.Set("stderr")
if *flStdin {
flAttach.Set("stdin")
}
}
}
parsedArgs := cmd.Args()
runCmd := []string{}
image := ""
@ -96,13 +113,15 @@ func ParseRun(args []string, stdout io.Writer) (*Config, error) {
Tty: *flTty,
OpenStdin: *flStdin,
Memory: *flMemory,
Detach: *flDetach,
AttachStdin: flAttach.Get("stdin"),
AttachStdout: flAttach.Get("stdout"),
AttachStderr: flAttach.Get("stderr"),
Env: flEnv,
Cmd: runCmd,
Image: image,
}
// When allocating stdin in attached mode, close stdin at client disconnect
if config.OpenStdin && !config.Detach {
if config.OpenStdin && config.AttachStdin {
config.StdinOnce = true
}
return config, nil