Add detach to exec

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2016-01-29 17:37:52 -08:00
parent e838be38d2
commit 92ab7309d5
2 changed files with 64 additions and 29 deletions

28
exec.go
View File

@ -43,6 +43,15 @@ var execCommand = cli.Command{
Name: "process,p",
Usage: "path to the process.json",
},
cli.BoolFlag{
Name: "detach,d",
Usage: "detach from the container's process",
},
cli.StringFlag{
Name: "pid-file",
Value: "",
Usage: "specify the file to write the process id to",
},
},
Action: func(context *cli.Context) {
if os.Geteuid() != 0 {
@ -61,7 +70,10 @@ func execProcess(context *cli.Context) (int, error) {
if err != nil {
return -1, err
}
bundle := container.Config().Rootfs
var (
detach = context.Bool("detach")
bundle = container.Config().Rootfs
)
rootuid, err := container.Config().HostUID()
if err != nil {
return -1, err
@ -71,15 +83,23 @@ func execProcess(context *cli.Context) (int, error) {
return -1, err
}
process := newProcess(*p)
tty, err := newTty(p.Terminal, process, rootuid, context.String("console"))
tty, err := setupIO(process, rootuid, context.String("console"), p.Terminal, detach)
if err != nil {
return -1, err
}
handler := newSignalHandler(tty)
defer handler.Close()
if err := container.Start(process); err != nil {
return -1, err
}
if pidFile := context.String("pid-file"); pidFile != "" {
if err := createPidile(pidFile, process); err != nil {
return -1, err
}
}
if detach {
return 0, nil
}
handler := newSignalHandler(tty)
defer handler.Close()
return handler.forward(process)
}

View File

@ -132,38 +132,17 @@ func startContainer(context *cli.Context, spec *specs.LinuxSpec, rspec *specs.Li
process.ExtraFiles = append(process.ExtraFiles, os.NewFile(uintptr(i), ""))
}
}
var tty *tty
if spec.Process.Terminal {
if tty, err = createTty(process, rootuid, context.String("console")); err != nil {
return -1, err
}
} else if detach {
if err := dupStdio(process, rootuid); err != nil {
return -1, err
}
} else {
if tty, err = createStdioPipes(process, rootuid); err != nil {
return -1, err
}
tty, err := setupIO(process, rootuid, context.String("console"), spec.Process.Terminal, detach)
if err != nil {
return -1, err
}
if err := container.Start(process); err != nil {
return -1, err
}
if pidFile := context.String("pid-file"); pidFile != "" {
pid, err := process.Pid()
if err != nil {
if err := createPidile(pidFile, process); err != nil {
return -1, err
}
f, err := os.Create(pidFile)
if err != nil {
logrus.WithField("pid", pid).Error("create pid file")
} else {
_, err = fmt.Fprintf(f, "%d", pid)
f.Close()
if err != nil {
logrus.WithField("error", err).Error("write pid file")
}
}
}
if detach {
return 0, nil
@ -209,3 +188,39 @@ func destroy(container libcontainer.Container) {
logrus.Error(err)
}
}
func setupIO(process *libcontainer.Process, rootuid int, console string, createTTY, detach bool) (*tty, error) {
// detach and createTty will not work unless a console path is passed
// so error out here before changing any terminal settings
if createTTY && detach && console == "" {
return nil, fmt.Errorf("cannot allocate tty if runc will detach")
}
if createTTY {
return createTty(process, rootuid, console)
}
if detach {
if err := dupStdio(process, rootuid); err != nil {
return nil, err
}
return nil, nil
}
return createStdioPipes(process, rootuid)
}
func createPidile(path string, process *libcontainer.Process) error {
pid, err := process.Pid()
if err != nil {
return err
}
f, err := os.Create(path)
if err != nil {
logrus.WithField("pid", pid).Error("create pid file")
} else {
_, err = fmt.Fprintf(f, "%d", pid)
f.Close()
if err != nil {
logrus.WithField("error", err).Error("write pid file")
}
}
return nil
}