exec.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  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/opencontainers/runc/libcontainer"
  10. // Blank import 'nsenter' so that init in that package will call c
  11. // function 'nsexec()' to do 'setns' before Go runtime take over,
  12. // it's used for join to exist ns like 'docker exec' command.
  13. _ "github.com/opencontainers/runc/libcontainer/nsenter"
  14. "github.com/opencontainers/runc/libcontainer/utils"
  15. )
  16. // Exec implements the exec driver Driver interface,
  17. // it calls libcontainer APIs to execute a container.
  18. func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, hooks execdriver.Hooks) (int, error) {
  19. active := d.activeContainers[c.ID]
  20. if active == nil {
  21. return -1, fmt.Errorf("No active container exists with ID %s", c.ID)
  22. }
  23. p := &libcontainer.Process{
  24. Args: append([]string{processConfig.Entrypoint}, processConfig.Arguments...),
  25. Env: c.ProcessConfig.Env,
  26. Cwd: c.WorkingDir,
  27. User: processConfig.User,
  28. }
  29. if processConfig.Privileged {
  30. p.Capabilities = execdriver.GetAllCapabilities()
  31. }
  32. config := active.Config()
  33. if err := setupPipes(&config, processConfig, p, pipes); err != nil {
  34. return -1, err
  35. }
  36. if err := active.Start(p); err != nil {
  37. return -1, err
  38. }
  39. if hooks.Start != nil {
  40. pid, err := p.Pid()
  41. if err != nil {
  42. p.Signal(os.Kill)
  43. p.Wait()
  44. return -1, err
  45. }
  46. hooks.Start(&c.ProcessConfig, pid)
  47. }
  48. ps, err := p.Wait()
  49. if err != nil {
  50. exitErr, ok := err.(*exec.ExitError)
  51. if !ok {
  52. return -1, err
  53. }
  54. ps = exitErr.ProcessState
  55. }
  56. return utils.ExitStatus(ps.Sys().(syscall.WaitStatus)), nil
  57. }