Пример #1
0
/*
	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
}
Пример #2
0
/*
	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
}
Пример #3
0
/*
	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
}