原文链接:https://blog.csdn.net/flyfreelyit/article/details/103697013
测试代码地址:https://github.com/kirinlabs/execshell
Golang 执行 shell 脚本,不接收返回值
// 返回一个 cmd 对象
cmd := exec.Command("sh", "-c", "./scripts/curl.sh")// 如果只执行命令,不接收返回值
cmd.Run()
Run(),命令其实是调用了 cmd.Start()和 cmd.Wait()两个方法,只返回一个 error 对象
Golang 执行 shell脚本,接收返回值
// 返回一个 cmd 对象
cmd := exec.Command("sh", "-c", "./scripts/curl.sh")// 收返回值[]byte, error
b,er:= cmd.Output()log.Pringln(string(b))
返回值就是 shell 脚本打印的日志信息,但这样有一个缺点,golang 接收 shell 脚本的打印结果,必须要等待 shell 脚本全部执行完成才能一次性返回
Golang 执行 shell脚本,并实时打印 shell 脚本输出日志信息
实际业务比如:异步任务调度系统、自动发布系统等都有可能需要 shell 脚本的配合来完成,就需要实时打印 shell 脚本的中每条命令的输出日志信息,便于查看任务进度等
package mainimport ("fmt""io""log""os/exec""strings"
)func asyncLog(reader io.ReadCloser) error {cache := ""buf := make([]byte, 1024, 1024)for {num, err := reader.Read(buf)if err != nil {if err == io.EOF || strings.Contains(err.Error(), "closed") {err = nil}return err}if num > 0 {oByte := buf[:num]h.logInfo = append(h.logInfo, oByte...)oSlice := strings.Split(string(oByte), "\n")line := strings.Join(oSlice[:len(oSlice)-1], "\n")fmt.Printf("%s%s\n", cache, line)cache = oSlice[len(oSlice)-1]}}return nil
}func execute() error {cmd := exec.Command("sh", "-c", "./scripts/curl.sh")stdout, _ := cmd.StdoutPipe()stderr, _ := cmd.StderrPipe()if err := cmd.Start(); err != nil {log.Printf("Error starting command: %s......", err.Error())return err}go asyncLog(stdout)go asyncLog(stderr)if err := cmd.Wait(); err != nil {log.Printf("Error waiting for command execution: %s......", err.Error())return err}return nil
}func main(){execute()
}
shell脚本,每秒打印时间,观察 Golang 对日志的实时输出
#!/bin/bash#print time
for((i=0;i<10;i++))
dosleep 1echo $(date +"%Y-%m-%d %H:%M:%S")
done