You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
1.8 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package process
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "os/exec"
  7. "time"
  8. )
  9. type Process struct {
  10. Label string
  11. ExecPath string
  12. Args []string
  13. Pid int
  14. StartTime time.Time
  15. EndTime time.Time
  16. Cmd *exec.Cmd `json:"-"`
  17. ExitState *os.ProcessState `json:"-"`
  18. InputFile io.Reader `json:"-"`
  19. OutputFile io.WriteCloser `json:"-"`
  20. WaitCh chan struct{} `json:"-"`
  21. }
  22. // execPath: command name
  23. // args: args to command. (should not include name)
  24. func StartProcess(label string, dir string, execPath string, args []string, inFile io.Reader, outFile io.WriteCloser) (*Process, error) {
  25. cmd := exec.Command(execPath, args...)
  26. cmd.Dir = dir
  27. cmd.Stdout = outFile
  28. cmd.Stderr = outFile
  29. cmd.Stdin = inFile
  30. if err := cmd.Start(); err != nil {
  31. return nil, err
  32. }
  33. proc := &Process{
  34. Label: label,
  35. ExecPath: execPath,
  36. Args: args,
  37. Pid: cmd.Process.Pid,
  38. StartTime: time.Now(),
  39. Cmd: cmd,
  40. ExitState: nil,
  41. InputFile: inFile,
  42. OutputFile: outFile,
  43. WaitCh: make(chan struct{}),
  44. }
  45. go func() {
  46. err := proc.Cmd.Wait()
  47. if err != nil {
  48. // fmt.Printf("Process exit: %v\n", err)
  49. if exitError, ok := err.(*exec.ExitError); ok {
  50. proc.ExitState = exitError.ProcessState
  51. }
  52. }
  53. proc.ExitState = proc.Cmd.ProcessState
  54. proc.EndTime = time.Now() // TODO make this goroutine-safe
  55. err = proc.OutputFile.Close()
  56. if err != nil {
  57. fmt.Printf("Error closing output file for %v: %v\n", proc.Label, err)
  58. }
  59. close(proc.WaitCh)
  60. }()
  61. return proc, nil
  62. }
  63. func (proc *Process) StopProcess(kill bool) error {
  64. defer proc.OutputFile.Close()
  65. if kill {
  66. // fmt.Printf("Killing process %v\n", proc.Cmd.Process)
  67. return proc.Cmd.Process.Kill()
  68. } else {
  69. // fmt.Printf("Stopping process %v\n", proc.Cmd.Process)
  70. return proc.Cmd.Process.Signal(os.Interrupt)
  71. }
  72. }