cmd_provider.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. cmd []string
  20. session *sh.Session
  21. }
  22. func newCmdProvider(c cmdConfig) (*cmdProvider, error) {
  23. // TODO: check config options
  24. provider := &cmdProvider{
  25. baseProvider: baseProvider{
  26. name: c.name,
  27. ctx: NewContext(),
  28. interval: c.interval,
  29. },
  30. cmdConfig: c,
  31. }
  32. provider.ctx.Set(_WorkingDirKey, c.workingDir)
  33. provider.ctx.Set(_LogDirKey, c.logDir)
  34. provider.ctx.Set(_LogFileKey, c.logFile)
  35. cmd, err := shlex.Split(c.command, true)
  36. if err != nil {
  37. return nil, err
  38. }
  39. provider.cmd = cmd
  40. return provider, nil
  41. }
  42. // Copied from go-sh
  43. func newEnviron(env map[string]string, inherit bool) []string { //map[string]string {
  44. environ := make([]string, 0, len(env))
  45. if inherit {
  46. for _, line := range os.Environ() {
  47. // if os environment and env collapses,
  48. // omit the os one
  49. k := strings.Split(line, "=")[0]
  50. if _, ok := env[k]; ok {
  51. continue
  52. }
  53. environ = append(environ, line)
  54. }
  55. }
  56. for k, v := range env {
  57. environ = append(environ, k+"="+v)
  58. }
  59. return environ
  60. }
  61. // TODO: implement this
  62. func (p *cmdProvider) Run() error {
  63. var cmd *exec.Cmd
  64. if len(p.cmd) == 1 {
  65. cmd = exec.Command(p.cmd[0])
  66. } else if len(p.cmd) > 1 {
  67. c := p.cmd[0]
  68. args := p.cmd[1:]
  69. cmd = exec.Command(c, args...)
  70. } else if len(p.cmd) == 0 {
  71. panic("Command length should be at least 1!")
  72. }
  73. 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. cmd.Env = newEnviron(env, true)
  84. logFile, err := os.OpenFile(p.LogFile(), os.O_WRONLY, 0644)
  85. if err != nil {
  86. return err
  87. }
  88. cmd.Stdout = logFile
  89. cmd.Stderr = logFile
  90. return cmd.Start()
  91. }
  92. // TODO: implement this
  93. func (p *cmdProvider) Terminate() {
  94. }
  95. // TODO: implement this
  96. func (p *cmdProvider) Hooks() {
  97. }