cmd_provider.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package worker
  2. import (
  3. "os"
  4. "os/exec"
  5. "strings"
  6. "github.com/anmitsu/go-shlex"
  7. "github.com/codeskyblue/go-sh"
  8. )
  9. type cmdConfig struct {
  10. name string
  11. upstreamURL, command string
  12. workingDir, logDir, logFile string
  13. interval int
  14. env map[string]string
  15. }
  16. type cmdProvider struct {
  17. baseProvider
  18. cmdConfig
  19. command []string
  20. cmd *exec.Cmd
  21. session *sh.Session
  22. }
  23. func newCmdProvider(c cmdConfig) (*cmdProvider, error) {
  24. // TODO: check config options
  25. provider := &cmdProvider{
  26. baseProvider: baseProvider{
  27. name: c.name,
  28. ctx: NewContext(),
  29. interval: c.interval,
  30. },
  31. cmdConfig: c,
  32. }
  33. provider.ctx.Set(_WorkingDirKey, c.workingDir)
  34. provider.ctx.Set(_LogDirKey, c.logDir)
  35. provider.ctx.Set(_LogFileKey, c.logFile)
  36. cmd, err := shlex.Split(c.command, true)
  37. if err != nil {
  38. return nil, err
  39. }
  40. provider.command = cmd
  41. return provider, nil
  42. }
  43. // Copied from go-sh
  44. func newEnviron(env map[string]string, inherit bool) []string { //map[string]string {
  45. environ := make([]string, 0, len(env))
  46. if inherit {
  47. for _, line := range os.Environ() {
  48. // if os environment and env collapses,
  49. // omit the os one
  50. k := strings.Split(line, "=")[0]
  51. if _, ok := env[k]; ok {
  52. continue
  53. }
  54. environ = append(environ, line)
  55. }
  56. }
  57. for k, v := range env {
  58. environ = append(environ, k+"="+v)
  59. }
  60. return environ
  61. }
  62. // TODO: implement this
  63. func (p *cmdProvider) Run() error {
  64. if len(p.command) == 1 {
  65. p.cmd = exec.Command(p.command[0])
  66. } else if len(p.command) > 1 {
  67. c := p.command[0]
  68. args := p.command[1:]
  69. p.cmd = exec.Command(c, args...)
  70. } else if len(p.command) == 0 {
  71. panic("Command length should be at least 1!")
  72. }
  73. p.cmd.Dir = p.WorkingDir()
  74. env := map[string]string{
  75. "TUNASYNC_MIRROR_NAME": p.Name(),
  76. "TUNASYNC_WORKING_DIR": p.WorkingDir(),
  77. "TUNASYNC_UPSTREAM_URL": p.upstreamURL,
  78. "TUNASYNC_LOG_FILE": p.LogFile(),
  79. }
  80. for k, v := range p.env {
  81. env[k] = v
  82. }
  83. p.cmd.Env = newEnviron(env, true)
  84. logFile, err := os.OpenFile(p.LogFile(), os.O_WRONLY|os.O_CREATE, 0644)
  85. if err != nil {
  86. return err
  87. }
  88. p.cmd.Stdout = logFile
  89. p.cmd.Stderr = logFile
  90. return p.cmd.Start()
  91. }
  92. func (p *cmdProvider) Wait() error {
  93. return p.cmd.Wait()
  94. }
  95. // TODO: implement this
  96. func (p *cmdProvider) Terminate() {
  97. }
  98. // TODO: implement this
  99. func (p *cmdProvider) Hooks() {
  100. }