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
相关推荐
玖玥拾1 小时前
C# 语言进阶(十五)C# 游戏服务端 MySQL 数据库
服务器·开发语言·网络·数据库·mysql·c#
铅笔侠_小龙虾2 小时前
Rust 学习目录
开发语言·学习·rust
考虑考虑2 小时前
Sentinel安装
java·后端·微服务
IT_陈寒2 小时前
SpringBoot自动配置失灵?你可能忘了这个关键注解
前端·人工智能·后端
云泽8082 小时前
从零吃透 C++ 异常:抛出捕获、栈展开、异常重抛与编码规范详解
开发语言·c++·代码规范
碎碎念_4922 小时前
SpringBoot + Vue 前后端分离从 0 到 1 完整环境配置流程
vue.js·spring boot·后端
灯澜忆梦2 小时前
GO---可见性规则
开发语言·golang
逝水无殇2 小时前
C# 文件的输入与输出详解
开发语言·数据库·后端·c#
YIAN3 小时前
从手写 Agent 工具到 MCP 协议:一文搞懂大模型跨进程跨语言工具调用
后端·agent·mcp
小兔崽子去哪了3 小时前
Docker 删除镜像后磁盘空间没有释放?
后端·docker·容器