github.com/dougm/docker@v1.5.0/daemon/execdriver/native/exec.go (about)

     1  // +build linux
     2  
     3  package native
     4  
     5  import (
     6  	"fmt"
     7  	"log"
     8  	"os"
     9  	"os/exec"
    10  	"path/filepath"
    11  	"runtime"
    12  
    13  	"github.com/docker/docker/daemon/execdriver"
    14  	"github.com/docker/docker/pkg/reexec"
    15  	"github.com/docker/libcontainer"
    16  	"github.com/docker/libcontainer/namespaces"
    17  )
    18  
    19  const execCommandName = "nsenter-exec"
    20  
    21  func init() {
    22  	reexec.Register(execCommandName, nsenterExec)
    23  }
    24  
    25  func nsenterExec() {
    26  	runtime.LockOSThread()
    27  
    28  	// User args are passed after '--' in the command line.
    29  	userArgs := findUserArgs()
    30  
    31  	config, err := loadConfigFromFd()
    32  	if err != nil {
    33  		log.Fatalf("docker-exec: unable to receive config from sync pipe: %s", err)
    34  	}
    35  
    36  	if err := namespaces.FinalizeSetns(config, userArgs); err != nil {
    37  		log.Fatalf("docker-exec: failed to exec: %s", err)
    38  	}
    39  }
    40  
    41  // TODO(vishh): Add support for running in priviledged mode and running as a different user.
    42  func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
    43  	active := d.activeContainers[c.ID]
    44  	if active == nil {
    45  		return -1, fmt.Errorf("No active container exists with ID %s", c.ID)
    46  	}
    47  	state, err := libcontainer.GetState(filepath.Join(d.root, c.ID))
    48  	if err != nil {
    49  		return -1, fmt.Errorf("State unavailable for container with ID %s. The container may have been cleaned up already. Error: %s", c.ID, err)
    50  	}
    51  
    52  	var term execdriver.Terminal
    53  
    54  	if processConfig.Tty {
    55  		term, err = NewTtyConsole(processConfig, pipes)
    56  	} else {
    57  		term, err = execdriver.NewStdConsole(processConfig, pipes)
    58  	}
    59  
    60  	processConfig.Terminal = term
    61  
    62  	args := append([]string{processConfig.Entrypoint}, processConfig.Arguments...)
    63  
    64  	return namespaces.ExecIn(active.container, state, args, os.Args[0], "exec", processConfig.Stdin, processConfig.Stdout, processConfig.Stderr, processConfig.Console,
    65  		func(cmd *exec.Cmd) {
    66  			if startCallback != nil {
    67  				startCallback(&c.ProcessConfig, cmd.Process.Pid)
    68  			}
    69  		})
    70  }