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.

75 lines
1.8 KiB

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, execPath string, args []string, inFile io.Reader, outFile io.WriteCloser) (*Process, error) {
  25. cmd := exec.Command(execPath, args...)
  26. cmd.Stdout = outFile
  27. cmd.Stderr = outFile
  28. cmd.Stdin = inFile
  29. if err := cmd.Start(); err != nil {
  30. return nil, err
  31. }
  32. proc := &Process{
  33. Label: label,
  34. ExecPath: execPath,
  35. Args: args,
  36. Pid: cmd.Process.Pid,
  37. StartTime: time.Now(),
  38. Cmd: cmd,
  39. ExitState: nil,
  40. InputFile: inFile,
  41. OutputFile: outFile,
  42. WaitCh: make(chan struct{}),
  43. }
  44. go func() {
  45. err := proc.Cmd.Wait()
  46. if err != nil {
  47. fmt.Printf("Process exit: %v\n", err)
  48. if exitError, ok := err.(*exec.ExitError); ok {
  49. proc.ExitState = exitError.ProcessState
  50. }
  51. }
  52. proc.ExitState = proc.Cmd.ProcessState
  53. proc.EndTime = time.Now() // TODO make this goroutine-safe
  54. err = proc.OutputFile.Close()
  55. if err != nil {
  56. fmt.Printf("Error closing output file for %v: %v\n", proc.Label, err)
  57. }
  58. close(proc.WaitCh)
  59. }()
  60. return proc, nil
  61. }
  62. func (proc *Process) StopProcess() error {
  63. defer proc.OutputFile.Close()
  64. if kill {
  65. fmt.Printf("Killing process %v\n", proc.Cmd.Process)
  66. return proc.Cmd.Process.Kill()
  67. } else {
  68. fmt.Printf("Stopping process %v\n", proc.Cmd.Process)
  69. return proc.Cmd.Process.Signal(os.Interrupt)
  70. }
  71. }