diff --git a/cmd/ctr/run.go b/cmd/ctr/run.go index 50c851bc6..ffe4c6ea7 100644 --- a/cmd/ctr/run.go +++ b/cmd/ctr/run.go @@ -92,6 +92,14 @@ var runCommand = cli.Command{ Name: "cwd", Usage: "specify the working directory of the process", }, + cli.BoolFlag{ + Name: "null-io", + Usage: "send all IO to /dev/null", + }, + cli.BoolFlag{ + Name: "detach,d", + Usage: "detach from the task after it has started execution", + }, }, snapshotterFlags...), Action: func(context *cli.Context) error { var ( @@ -101,6 +109,7 @@ var runCommand = cli.Command{ id = context.Args().Get(1) imageRef = context.Args().First() tty = context.Bool("tty") + detach = context.Bool("detach") ) defer cancel() @@ -118,20 +127,20 @@ var runCommand = cli.Command{ if err != nil { return err } - if context.Bool("rm") { + if context.Bool("rm") && !detach { defer container.Delete(ctx, containerd.WithSnapshotCleanup) } - task, err := newTask(ctx, client, container, context.String("checkpoint"), tty) + task, err := newTask(ctx, client, container, context.String("checkpoint"), tty, context.Bool("null-io")) if err != nil { return err } - defer task.Delete(ctx) - - statusC, err := task.Wait(ctx) - if err != nil { - return err + var statusC <-chan containerd.ExitStatus + if !detach { + defer task.Delete(ctx) + if statusC, err = task.Wait(ctx); err != nil { + return err + } } - var con console.Console if tty { con = console.Current() @@ -143,6 +152,9 @@ var runCommand = cli.Command{ if err := task.Start(ctx); err != nil { return err } + if detach { + return nil + } if tty { if err := handleConsoleResize(ctx, task, con); err != nil { logrus.WithError(err).Error("console resize") @@ -151,7 +163,6 @@ var runCommand = cli.Command{ sigc := forwardAllSignals(ctx, task) defer stopCatch(sigc) } - status := <-statusC code, _, err := status.Result() if err != nil { diff --git a/cmd/ctr/run_unix.go b/cmd/ctr/run_unix.go index 04be5ab8d..c890a61a5 100644 --- a/cmd/ctr/run_unix.go +++ b/cmd/ctr/run_unix.go @@ -114,12 +114,15 @@ func newContainer(ctx gocontext.Context, client *containerd.Client, context *cli return client.NewContainer(ctx, id, cOpts...) } -func newTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, checkpoint string, tty bool) (containerd.Task, error) { +func newTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, checkpoint string, tty, nullIO bool) (containerd.Task, error) { if checkpoint == "" { io := containerd.Stdio if tty { io = containerd.StdioTerminal } + if nullIO { + io = containerd.NullIO + } return container.NewTask(ctx, io) } im, err := client.GetImage(ctx, checkpoint) diff --git a/cmd/ctr/run_windows.go b/cmd/ctr/run_windows.go index 8712663b6..2879faec6 100644 --- a/cmd/ctr/run_windows.go +++ b/cmd/ctr/run_windows.go @@ -117,10 +117,13 @@ func newContainer(ctx gocontext.Context, client *containerd.Client, context *cli ) } -func newTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, _ string, tty bool) (containerd.Task, error) { +func newTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, _ string, tty, nullIO bool) (containerd.Task, error) { io := containerd.Stdio if tty { io = containerd.StdioTerminal } + if nullIO { + io = containerd.NullIO + } return container.NewTask(ctx, io) } diff --git a/cmd/ctr/start.go b/cmd/ctr/start.go index 087f6c684..69d266bd1 100644 --- a/cmd/ctr/start.go +++ b/cmd/ctr/start.go @@ -11,6 +11,12 @@ var taskStartCommand = cli.Command{ Name: "start", Usage: "start a container that have been created", ArgsUsage: "CONTAINER", + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "null-io", + Usage: "send all IO to /dev/null", + }, + }, Action: func(context *cli.Context) error { var ( err error @@ -40,7 +46,7 @@ var taskStartCommand = cli.Command{ tty := spec.Process.Terminal - task, err := newTask(ctx, client, container, "", tty) + task, err := newTask(ctx, client, container, "", tty, context.Bool("null-io")) if err != nil { return err }