(subcommand string, withEnvironment bool, withMonitoring bool)
| 108 | } |
| 109 | |
| 110 | func RunCommand(subcommand string, withEnvironment bool, withMonitoring bool) int { |
| 111 | var monitoringWaitGroup sync.WaitGroup |
| 112 | |
| 113 | startTime := makeStamp() |
| 114 | series := formatStamp(startTime) |
| 115 | schedule := "" |
| 116 | |
| 117 | if withMonitoring { |
| 118 | monitoringWaitGroup.Add(1) |
| 119 | if runtime.GOOS == "windows" { |
| 120 | schedule = GetNextRunFromMonitorKey(monitorCode) |
| 121 | } |
| 122 | go sendPing("run", monitorCode, subcommand, series, startTime, nil, nil, nil, schedule, &monitoringWaitGroup) |
| 123 | } |
| 124 | |
| 125 | log(fmt.Sprintf("Running subcommand: %s", subcommand)) |
| 126 | |
| 127 | execCmd := makeSubcommandExec(subcommand) |
| 128 | if withEnvironment { |
| 129 | execCmd.Env = os.Environ() |
| 130 | } else { |
| 131 | execCmd.Env = makeCronLikeEnv() |
| 132 | } |
| 133 | execCmd.Env = append(execCmd.Env, "CRONITOR_EXEC=1") |
| 134 | |
| 135 | // Handle stdin to the subcommand - improved pipe handling |
| 136 | execCmdStdin, err := execCmd.StdinPipe() |
| 137 | if err != nil { |
| 138 | log(fmt.Sprintf("Failed to create stdin pipe: %v", err)) |
| 139 | } else { |
| 140 | defer execCmdStdin.Close() |
| 141 | go func() { |
| 142 | defer execCmdStdin.Close() |
| 143 | io.Copy(execCmdStdin, os.Stdin) |
| 144 | }() |
| 145 | } |
| 146 | |
| 147 | // Proxy and copy the command's stdout if the filesystem is available |
| 148 | tempFile, err := getTempFile() |
| 149 | if err == nil { |
| 150 | defer tempFile.Close() |
| 151 | execCmd.Stdout = io.MultiWriter(os.Stdout, tempFile) |
| 152 | } else { |
| 153 | log(err.Error()) |
| 154 | execCmd.Stdout = os.Stdout |
| 155 | } |
| 156 | |
| 157 | // Combine stdout and stderr from the command into a single buffer which we'll stream as stdout |
| 158 | // Alternatively we could pass stderr from the subcommand but I've chosen to only use it for CronitorCLI errors at the moment |
| 159 | execCmd.Stderr = execCmd.Stdout |
| 160 | |
| 161 | // Invoke subcommand and send a message when it's done |
| 162 | waitCh := make(chan error, 16) |
| 163 | go func() { |
| 164 | defer close(waitCh) |
| 165 | |
| 166 | // Brief pause to allow gochannel selects |
| 167 | time.Sleep(20 * time.Millisecond) |
no test coverage detected