exec.go 1.9 KB

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