Golang - 执行 shell 脚本,并实时按行打印 shell 脚本输出信息

原文链接:https://blog.csdn.net/flyfreelyit/article/details/103697013

测试代码地址:https://github.com/kirinlabs/execshell

Golang 执行 shell 脚本,不接收返回值

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

Run(),命令其实是调用了 cmd.Start()和 cmd.Wait()两个方法,只返回一个 error 对象

Golang 执行 shell脚本,接收返回值

Go 复制代码
// 返回一个 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 脚本的中每条命令的输出日志信息,便于查看任务进度等

Go 复制代码
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脚本,每秒打印时间,观察 Golang 对日志的实时输出

Go 复制代码
#!/bin/bash
 
#print time
for((i=0;i<10;i++))
do
    sleep 1
    echo $(date +"%Y-%m-%d %H:%M:%S")
done
相关推荐
Amour恋空6 分钟前
Java多线程
java·开发语言·python
小陈工11 分钟前
2026年3月28日技术资讯洞察:5G-A边缘计算落地、低延迟AI推理革命与工业智造新范式
开发语言·人工智能·后端·python·5g·安全·边缘计算
第二只羽毛33 分钟前
C++ 高并发内存池1
大数据·开发语言·c++·开源
不想看见40440 分钟前
C++/Qt 实习岗位深度解析【结合一次研发实习谈感受】
开发语言·c++·qt
sjmaysee1 小时前
Java框架SpringBoot(一)
java·开发语言·spring boot
azhou的代码园1 小时前
基于SpringBoot+微信小程序的图片识别科普系统
spring boot·后端·微信小程序
寒秋花开曾相惜1 小时前
(学习笔记)3.8 指针运算(3.8.3 嵌套的数组& 3.8.4 定长数组)
java·开发语言·笔记·学习·算法
想唱rap1 小时前
Linux线程
java·linux·运维·服务器·开发语言·mysql
Tony Bai1 小时前
Rust 看了流泪,AI 看了沉默:扒开 Go 泛型最让你抓狂的“残疾”类型推断
开发语言·人工智能·后端·golang·rust
njidf1 小时前
C++与Qt图形开发
开发语言·c++·算法