exec.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // +build linux
  2. package native
  3. import (
  4. "fmt"
  5. "os"
  6. "os/exec"
  7. "syscall"
  8. "github.com/docker/docker/daemon/execdriver"
  9. "github.com/docker/libcontainer"
  10. _ "github.com/docker/libcontainer/nsenter"
  11. "github.com/docker/libcontainer/utils"
  12. )
  13. // TODO(vishh): Add support for running in priviledged mode and running as a different user.
  14. func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
  15. active := d.activeContainers[c.ID]
  16. if active == nil {
  17. return -1, fmt.Errorf("No active container exists with ID %s", c.ID)
  18. }
  19. var term execdriver.Terminal
  20. var err error
  21. p := &libcontainer.Process{
  22. Args: append([]string{processConfig.Entrypoint}, processConfig.Arguments...),
  23. Env: c.ProcessConfig.Env,
  24. Cwd: c.WorkingDir,
  25. User: c.ProcessConfig.User,
  26. }
  27. if processConfig.Tty {
  28. config := active.Config()
  29. rootuid, err := config.HostUID()
  30. if err != nil {
  31. return -1, err
  32. }
  33. cons, err := p.NewConsole(rootuid)
  34. if err != nil {
  35. return -1, err
  36. }
  37. term, err = NewTtyConsole(cons, pipes, rootuid)
  38. } else {
  39. p.Stdout = pipes.Stdout
  40. p.Stderr = pipes.Stderr
  41. p.Stdin = pipes.Stdin
  42. term = &execdriver.StdConsole{}
  43. }
  44. if err != nil {
  45. return -1, err
  46. }
  47. processConfig.Terminal = term
  48. if err := active.Start(p); err != nil {
  49. return -1, err
  50. }
  51. if startCallback != nil {
  52. pid, err := p.Pid()
  53. if err != nil {
  54. p.Signal(os.Kill)
  55. p.Wait()
  56. return -1, err
  57. }
  58. startCallback(&c.ProcessConfig, pid)
  59. }
  60. ps, err := p.Wait()
  61. if err != nil {
  62. exitErr, ok := err.(*exec.ExitError)
  63. if !ok {
  64. return -1, err
  65. }
  66. ps = exitErr.ProcessState
  67. }
  68. return utils.ExitStatus(ps.Sys().(syscall.WaitStatus)), nil
  69. }