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

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 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 Create(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 Stop(proc *Process, kill bool) 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. }