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.

94 lines
2.0 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. "bytes"
  4. "fmt"
  5. "io"
  6. "os"
  7. "os/exec"
  8. "time"
  9. )
  10. func makeFile(prefix string) (string, *os.File) {
  11. now := time.Now()
  12. path := fmt.Sprintf("%v_%v.out", prefix, now.Format("2006_01_02_15_04_05_MST"))
  13. file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
  14. if err != nil {
  15. panic(err)
  16. }
  17. return path, file
  18. }
  19. type Process struct {
  20. Label string
  21. ExecPath string
  22. Pid int
  23. StartTime time.Time
  24. EndTime time.Time
  25. OutputPath string
  26. Cmd *exec.Cmd `json:"-"`
  27. ExitState *os.ProcessState `json:"-"`
  28. OutputFile *os.File `json:"-"`
  29. }
  30. const (
  31. ProcessModeStd = iota
  32. ProcessModeDaemon
  33. )
  34. // execPath: command name
  35. // args: args to command. (should not include name)
  36. func Create(mode int, label string, execPath string, args []string, input string) (*Process, error) {
  37. outPath, outFile := makeFile(label)
  38. cmd := exec.Command(execPath, args...)
  39. switch mode {
  40. case ProcessModeStd:
  41. cmd.Stdout = io.MultiWriter(os.Stdout, outFile)
  42. cmd.Stderr = io.MultiWriter(os.Stderr, outFile)
  43. cmd.Stdin = nil
  44. case ProcessModeDaemon:
  45. cmd.Stdout = outFile
  46. cmd.Stderr = outFile
  47. cmd.Stdin = nil
  48. }
  49. if input != "" {
  50. cmd.Stdin = bytes.NewReader([]byte(input))
  51. }
  52. if err := cmd.Start(); err != nil {
  53. return nil, err
  54. } else {
  55. fmt.Printf("Success!")
  56. }
  57. proc := &Process{
  58. Label: label,
  59. ExecPath: execPath,
  60. Pid: cmd.Process.Pid,
  61. StartTime: time.Now(),
  62. OutputPath: outPath,
  63. Cmd: cmd,
  64. ExitState: nil,
  65. OutputFile: outFile,
  66. }
  67. go func() {
  68. Wait(proc)
  69. proc.EndTime = time.Now() // TODO make this goroutine-safe
  70. }()
  71. return proc, nil
  72. }
  73. func Wait(proc *Process) error {
  74. exitErr := proc.Cmd.Wait()
  75. if exitErr != nil {
  76. fmt.Printf("Process exit: %v\n", exitErr)
  77. proc.ExitState = exitErr.(*exec.ExitError).ProcessState
  78. }
  79. return exitErr
  80. }
  81. func Stop(proc *Process, kill bool) error {
  82. if kill {
  83. return proc.Cmd.Process.Kill()
  84. } else {
  85. return proc.Cmd.Process.Signal(os.Interrupt)
  86. }
  87. }