Golang - execute shell scripts and print shell script output information line by line in real time


Original link: https://blog.csdn.net/flyfreelyit/article/details/103697013

Test code address: https://github.com/kirinlabs/execshell

Golang executes shell scripts and does not receive return values

// 返回一个 cmd 对象
cmd := exec.Command("sh", "-c", "./scripts/curl.sh")
 
// 如果只执行命令,不接收返回值
cmd.Run()


Run(), the command actually calls the cmd.Start() and cmd.Wait() methods, and only returns an error object.

Golang executes the shell script and receives the return value

// 返回一个 cmd 对象
cmd := exec.Command("sh", "-c", "./scripts/curl.sh")
 
// 收返回值[]byte, error
b,er:= cmd.Output()
 
log.Pringln(string(b))


        The return value is the log information printed by the shell script, but this has a disadvantage. Golang receives the print results of the shell script and must wait for the shell script to be fully executed before it can return at once.

Golang executes the shell script and prints the shell script output log information in real time.
Actual businesses such as asynchronous task scheduling systems, automatic publishing systems, etc. may require the cooperation of shell scripts to complete, and the output of each command in the shell script needs to be printed in real time. Log information for easy viewing of task progress, etc.

package main
 
import (
    "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 script, print time per second, observe Golang’s real-time output of logs

#!/bin/bash
 
#print time
for((i=0;i<10;i++))
do
    sleep 1
    echo $(date +"%Y-%m-%d %H:%M:%S")
done

Guess you like

Origin blog.csdn.net/xuezhangjun0121/article/details/135253381