/* Execute a command (using arguments 'args') Redirect stdout to outFile (unless file name is empty) Redirect stderr to errFile (unless file name is empty) Write exit code to exitFile (unless file name is empty) Timeout after timeout seconds (unless time is zero) */ func (be *BdsExec) executeCommand() int { if DEBUG { log.Printf("Debug: executeCommand %s\n", be.command) } // Redirect all signals to channel (e.g. Ctrl-C) osSignal := make(chan os.Signal) if be.taskLoggerFile != "" { signal.Notify(osSignal) // Capture all signals } else { // Set a new process group. // Since we want to kill all child processes, we'll send a kill signal to this process group. // But we don't want to kill the calling program... // fmt.Fprintf(os.Stderr, "bds: setting new process group\n") if err := syscall.Setpgid(0, 0); err != nil { // During an ssh remote execution we will no be albe to do this. // In this case, we assume that the SSH daemon will catch the sinals // and kill al child processes. if DEBUG { log.Printf("Error redirecting signals: %s", err) } } } // Create command be.cmd = exec.Command(be.command) be.cmd.Args = be.cmdargs // Copy stdout stdout := tee.NewTee(be.outFile, false) defer stdout.Close() be.cmd.Stdout = stdout // Copy stderr stderr := tee.NewTee(be.errFile, true) defer stderr.Close() be.cmd.Stderr = stderr // Connect to stdin be.cmd.Stdin = os.Stdin // Start process err := be.cmd.Start() if err != nil { log.Fatal(err) } be.exitCode = be.executeCommandTimeout(osSignal) if DEBUG { log.Printf("Debug, executeCommand: Exit code %d\n", be.exitCode) } return be.exitCode }
/* Execute a command (using arguments 'args') Redirect stdout to outFile (unless file name is empty) Redirect stderr to errFile (unless file name is empty) Write exit code to exitFile (unless file name is empty) Timeout after timeout seconds (unless time is zero) */ func executeCommand(command string, args []string, timeSecs int, outFile, errFile, exitFile string) int { if DEBUG { log.Printf("Debug: executeCommand %s\n", command) } // Redirect all signals to channel (e.g. Ctrl-C) osSignal := make(chan os.Signal) if taskLoggerFile != "" { signal.Notify(osSignal) // Capture all signals } else { // Set a new process group. // Since we want to kill all child processes, we'll send a kill signal to this process group. // But we don't want to kill the calling program... // fmt.Fprintf(os.Stderr, "bds: setting new process group\n") if err := syscall.Setpgid(0, 0); err != nil { // During an ssh remote execution we will no be albe to do this. // In this case, we assume that the SSH daemon will catch the sinals // and kill al child processes. if DEBUG { log.Printf("Error redirecting signals: %s", err) } } } // Create command cmd := exec.Command(command) cmd.Args = args stdout := tee.NewTee(outFile, false) defer stdout.Close() cmd.Stdout = stdout // stdout, err := cmd.StdoutPipe() // if err != nil { // log.Fatal(err) // } // // // Copy to STDOUT to file (or to stdout) // if (outFile == "") || (outFile == "-") { // go tee(os.Stdout, stdout, false) // } else { // stdoutFile, err := os.Create(outFile) // if err != nil { // log.Fatal(err) // } // defer stdoutFile.Close() // go tee(stdoutFile, stdout, false) // } // stderr, err := cmd.StderrPipe() // if err != nil { // log.Fatal(err) // } // // // Copy to STDERR to file (or to stderr) // if (errFile == "") || (errFile == "-") { // go tee(os.Stderr, stderr, true) // } else { // stderrFile, err := os.Create(errFile) // if err != nil { // log.Fatal(err) // } // defer stderrFile.Close() // go tee(stderrFile, stderr, true) // } // Start process err := cmd.Start() if err != nil { log.Fatal(err) } exitCode := executeCommandTimeout(cmd, timeSecs, exitFile, osSignal) return exitCode }
/* Execute a command (using arguments 'args') Redirect stdout to outFile (unless file name is empty) Redirect stderr to errFile (unless file name is empty) Write exit code to exitFile (unless file name is empty) Timeout after timeout seconds (unless time is zero) */ func (be *BdsExec) executeCommand() int { if DEBUG { log.Printf("Debug, executeCommand %s\n", be.command) } // Redirect all signals to channel (e.g. Ctrl-C) osSignal := make(chan os.Signal) if be.taskLoggerFile != "" { // Main bds program signal.Notify(osSignal) // Capture all signals } else { // Set a new process group. // We want to be able to kill all child processes, without killing the // calling program. E.g. When running using a local executor, the Java Bds // calls 'bds exec', so sending a kill to the group when a timeOut occurs, // would also kill the parent Java program and kill the whole bds execution // (clearly not what we want). // To avoid this, we create a new group thus we can send a kill signal to // this new process group. gpidOri, _ := syscall.Getpgid(0) if err := syscall.Setpgid(0, 0); err != nil { // During an ssh remote execution we will no be albe to do this. // In this case, we assume that the SSH daemon will catch the sinals // and kill al child processes. if DEBUG { log.Printf("Error setting process group: %s", err) } } if DEBUG { gpidNew, _ := syscall.Getpgid(0) log.Printf("Info: Setting new process group. Original GPID: %d, new GPID: %d\n", gpidOri, gpidNew) } } // Create command be.cmd = exec.Command(be.command) be.cmd.Args = be.cmdargs // Copy stdout stdout := tee.NewTee(be.outFile, false) defer stdout.Close() be.cmd.Stdout = stdout // Copy stderr stderr := tee.NewTee(be.errFile, true) defer stderr.Close() be.cmd.Stderr = stderr // Connect to stdin be.cmd.Stdin = os.Stdin // Start process err := be.cmd.Start() if err != nil { log.Fatal(err) } be.exitCode = be.executeCommandTimeout(osSignal) if DEBUG { log.Printf("Debug, executeCommand: Exit code %d\n", be.exitCode) } return be.exitCode }