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

6 篇文章 0 订阅

 

测试代码地址: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 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 对日志的实时输出

#!/bin/bash

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

 

Golang执行shell脚本有几种方式。引用\[1\]中的代码展示了一种方式,即使用`exec.Command`函数创建一个cmd对象,然后使用`cmd.Run()`来执行命令,但不接收返回值。这种方式适用于只需要执行命令而不需要获取返回值的情况。 如果需要获取shell脚本的返回值,可以使用引用\[2\]中的代码。同样是使用`exec.Command`函数创建cmd对象,但是使用`cmd.Output()`来获取返回值。`cmd.Output()`返回一个`\[\]byte`类型的值和一个`error`类型的值,其中`\[\]byte`类型的值是shell脚本输出结果。 另外,引用\[3\]中的代码展示了使用`cmd.StdoutPipe()`来获取命令的标准输出。这个函数返回一个管道,可以在命令启动时连接到命令的标准输出。然后使用`ioutil.ReadAll()`函数从管道中读取输出结果。 以上是几种在Golang执行shell脚本的方式,具体使用哪种方式取决于你的需求。 #### 引用[.reference_title] - *1* *2* [Golang 执行 shell 脚本,并实时按行打印 shell 脚本输出信息](https://blog.csdn.net/flyfreelyit/article/details/103697013)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [golang执行shell命令的几种方式](https://blog.csdn.net/qq_31389153/article/details/127615334)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值