Files
ProjectOctopus/agent-go/executor/FunctionalExecutor.go
2023-10-18 10:39:38 +08:00

226 lines
6.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package executor
import (
"bufio"
"bytes"
"fmt"
"io"
"os/exec"
"strings"
)
// AllCommandExecutor 正确或者错误的信息全部收集,共同返回
func AllCommandExecutor(singleLineCommand []string) (resultOk bool, resultLog []string) {
// result
var resultSlice []string
resultOk = true
cmd := exec.Command(singleLineCommand[0], singleLineCommand[1:]...)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.DebugF("command %v stdout error => %v", singleLineCommand, err)
resultOk = false
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.DebugF("command %v stderr error => %v", singleLineCommand, err)
resultOk = false
}
if err := cmd.Start(); err != nil {
log.DebugF("command %v runtime error => %v", singleLineCommand, err)
resultOk = false
}
// 收集错误或者
resultSlice = collectOutput(stdout, resultSlice)
resultSlice = collectOutput(stderr, resultSlice)
if err := cmd.Wait(); err != nil {
log.DebugF("command %v result error => %v", singleLineCommand, err)
resultOk = false
}
log.DebugF("all out command executor result are => %v", resultSlice)
return resultOk, resultSlice
}
// AllCompleteExecutor 多行命令的执行函数,返回执行正确与否和执行结果
func AllCompleteExecutor(multiCommand [][]string) (resultOk bool, resultLog []string) {
var result []string
resultOk = true
for _, singleLineCommand := range multiCommand {
ok, resultLog := AllCommandExecutor(singleLineCommand)
if !ok {
// 执行出错
resultOk = false
}
result = append(result, resultLog...)
}
return resultOk, result
}
// FormatAllCommandExecutor 收集全部执行结果、错误并且返回
func FormatAllCommandExecutor(singleLineCommand []string) ([]string, error) {
// result
var resultSlice []string
var resultError error
cmd := exec.Command(singleLineCommand[0], singleLineCommand[1:]...)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.ErrorF("command %v stdout error => %v", singleLineCommand, err)
resultError = err
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.ErrorF("command %v stderr error => %v", singleLineCommand, err)
resultError = err
}
if err := cmd.Start(); err != nil {
log.ErrorF("command %v runtime error => %v", singleLineCommand, err)
}
resultSlice = append(resultSlice, fmt.Sprintf(" 开始执行命令 ====> %s", singleLineCommand), "↓↓↓ 命令 输出 如下 ↓↓↓")
resultSlice = collectOutput(stdout, resultSlice)
resultSlice = append(resultSlice, "↓↓↓ 命令 错误 如下 ↓↓↓")
resultSlice = collectOutput(stderr, resultSlice)
if err := cmd.Wait(); err != nil {
log.ErrorF("command %v result error => %v", singleLineCommand, err)
resultError = err
}
log.DebugF("real time exec result are %v", resultSlice)
return resultSlice, resultError
}
func PipelineCommandExecutor(pipelineCommand [][]string) (resultOk bool, resultLog []string) {
if len(pipelineCommand) == 0 {
return true, nil
} else if len(pipelineCommand) == 1 {
log.Debug("输入的PipelineCommand长度有误")
return AllCommandExecutor(pipelineCommand[0])
}
var c []string
cmd1 := exec.Command(pipelineCommand[0][0], pipelineCommand[0][1:]...)
var outputBuf1 bytes.Buffer
cmd1.Stdout = &outputBuf1
if err := cmd1.Start(); err != nil {
sprintf := fmt.Sprintf("Error: The first command can not be startup %s", err)
return false, append(c, sprintf)
}
if err := cmd1.Wait(); err != nil {
sprintf := fmt.Sprintf("Error: Couldn't wait for the first command: %s", err)
return false, append(c, sprintf)
}
for i := 1; i < len(pipelineCommand); i++ {
cmd2 := exec.Command(pipelineCommand[i][0], pipelineCommand[i][1:]...)
sprintf := fmt.Sprintf("current command is %s", pipelineCommand[i])
c = append(c, sprintf)
cmd2.Stdin = &outputBuf1
var outputBuf2 bytes.Buffer
cmd2.Stdout = &outputBuf2
if err := cmd2.Start(); err != nil {
sprintf := fmt.Sprintf("Error: The second command can not be startup: %s", err)
return false, append(c, sprintf)
}
if err := cmd2.Wait(); err != nil {
sprintf := fmt.Sprintf("Error: Couldn't wait for the second command: %s", err)
return false, append(c, sprintf)
}
// change
outputBuf1 = outputBuf2
}
s := outputBuf1.String()
split := strings.Split(s, "\n")
return true, split
}
// PureResultSingleExecute 执行单行命令,忽略输出,只对执行成功与否负责
func PureResultSingleExecute(singleCommand []string) (resultOK bool) {
cmd := exec.Command(singleCommand[0], singleCommand[1:]...)
err := cmd.Run()
if err != nil {
log.ErrorF("指令 %s 执行 错误, 错误内容为 %s", singleCommand, err.Error())
return false
} else {
log.DebugF("指令 %s 执行 成功", singleCommand)
return true
}
}
// PureResultSingleExecuteBatch 批量 执行单行命令,忽略输出,只对执行成功与否负责
func PureResultSingleExecuteBatch(singleCommandList [][]string) (resultOK bool) {
result := true
for _, singleCommand := range singleCommandList {
if !PureResultSingleExecute(singleCommand) {
result = false
}
}
return result
}
// ReadTimeCommandExecutor 执行命令,并且实时返回结果
func ReadTimeCommandExecutor(singleLineCommand []string) {
cmd := exec.Command(singleLineCommand[0], singleLineCommand[1:]...)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.ErrorF("command %v stdout error => %v", singleLineCommand, err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.ErrorF("command %v stderr error => %v", singleLineCommand, err)
}
if err := cmd.Start(); err != nil {
log.ErrorF("command %v runtime error => %v", singleLineCommand, err)
}
go realTimeOutput(stdout)
go realTimeOutput(stderr)
if err := cmd.Wait(); err != nil {
log.ErrorF("command %v result error => %v", singleLineCommand, err)
}
}
func realTimeOutput(r io.Reader) {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
func collectOutput(r io.Reader, resultSlice []string) []string {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
resultLine := scanner.Text()
resultSlice = append(resultSlice, resultLine)
// debug usage
//fmt.Println(resultLine)
}
return resultSlice
}