go调用shell命令两种方式实现(有无返回值)

 更新时间:2021年12月08日 10:41:07   作者:风逸者儿  
本文主要介绍了go调用shell命令两种方式实现(有无返回值),主要用于执行shell命令,并且返回shell的标准输出,具有一定的参考价值,感兴趣的可以了解一下

阻塞方式(需要执行结果)

主要用于执行shell命令,并且返回shell的标准输出

适用于执行普通非阻塞shell命令,且需要shell标准输出的

//阻塞式的执行外部shell命令的函数,等待执行完毕并返回标准输出
func exec_shell(s string) (string, error){
    //函数返回一个*Cmd,用于使用给出的参数执行name指定的程序
    cmd := exec.Command("/bin/bash", "-c", s)

    //读取io.Writer类型的cmd.Stdout,再通过bytes.Buffer(缓冲byte类型的缓冲器)将byte类型转化为string类型(out.String():这是bytes类型提供的接口)
    var out bytes.Buffer
    cmd.Stdout = &out

    //Run执行c包含的命令,并阻塞直到完成。  这里stdout被取出,cmd.Wait()无法正确获取stdin,stdout,stderr,则阻塞在那了
    err := cmd.Run()
    checkErr(err)
    return out.String(), err
}

需要对shell标准输出的逐行实时进行处理的

func execCommand(commandName string, params []string) bool {
    //函数返回一个*Cmd,用于使用给出的参数执行name指定的程序
    cmd := exec.Command(commandName, params...)

    //显示运行的命令
    fmt.Println(cmd.Args)
    //StdoutPipe方法返回一个在命令Start后与命令标准输出关联的管道。Wait方法获知命令结束后会关闭这个管道,一般不需要显式的关闭该管道。
    stdout, err := cmd.StdoutPipe()

    if err != nil {
        fmt.Println(err)
        return false
    }

    cmd.Start()
    //创建一个流来读取管道内内容,这里逻辑是通过一行一行的读取的
    reader := bufio.NewReader(stdout)

    //实时循环读取输出流中的一行内容
    for {
        line, err2 := reader.ReadString('\n')
        if err2 != nil || io.EOF == err2 {
            break
        }
        fmt.Println(line)
    }

    //阻塞直到该命令执行完成,该命令必须是被Start方法开始执行的
    cmd.Wait()
    return true
}

非阻塞方式(不需要执行结果)

通过shell调用自己的程序,并且程序是死循环,此时无法获取返回结果(否则程序会一直阻塞直至调用的 程序结束)

适用于调用自己写的程序(服务器死循环,且不需要返回结果的)

//不需要执行命令的结果与成功与否,执行命令马上就返回
func exec_shell_no_result(command string) {
    //处理启动参数,通过空格分离 如:setsid /home/luojing/gotest/src/test_main/iwatch/test/while_little &
    command_name_and_args := strings.FieldsFunc(command, splite_command)
    //开始执行c包含的命令,但并不会等待该命令完成即返回
    cmd.Start()
        if err != nil {
        fmt.Printf("%v: exec command:%v error:%v\n", get_time(), command, err)
    }
    fmt.Printf("Waiting for command:%v to finish...\n", command)
    //阻塞等待fork出的子进程执行的结果,和cmd.Start()配合使用[不等待回收资源,会导致fork出执行shell命令的子进程变为僵尸进程]
    err = cmd.Wait()
    if err != nil {
        fmt.Printf("%v: Command finished with error: %v\n", get_time(), err)
    }
    return
}
/错误处理函数
func checkErr(err error) {
    if err != nil {
        fmt.Println(err)
        panic(err)  
    }
}

官网的标准中文库

引用部分文档

func (*Cmd) Run
func (c *Cmd) Run() error

Run执行c包含的命令,并阻塞直到完成。
如果命令成功执行,stdin、stdout、stderr的转交没有问题,并且返回状态码为0,方法的返回值为nil;如果命令没有执行或者执行失败,会返回*ExitError类型的错误;否则返回的error可能是表示I/O问题。

func (*Cmd) Start
func (c *Cmd) Start() error

Start开始执行c包含的命令,但并不会等待该命令完成即返回。Wait方法会返回命令的返回状态码并在命令返回后释放相关的资源。

func (*Cmd) Wait
func (c *Cmd) Wait() error

Wait会阻塞直到该命令执行完成,该命令必须是被Start方法开始执行的。

如果命令成功执行,stdin、stdout、stderr的转交没有问题,并且返回状态码为0,方法的返回值为nil;如果命令没有执行或者执行失败,会返回*ExitError类型的错误;否则返回的error可能是表示I/O问题。Wait方法会在命令返回后释放相关的资源。

func (*Cmd) Output
func (c *Cmd) Output() ([]byte, error)

执行命令并返回标准输出的切片。

func (*Cmd) StderrPipe
func (c *Cmd) StderrPipe() (io.ReadCloser, error)

StderrPipe方法返回一个在命令Start后与命令标准错误输出关联的管道。Wait方法获知命令结束后会关闭这个管道,一般不需要显式的关闭该管道。但是在从管道读取完全部数据之前调用Wait是错误的;同样使用StderrPipe方法时调用Run函数也是错误的。

到此这篇关于go调用shell命令两种方式实现(有无返回值)的文章就介绍到这了,更多相关go调用shell内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • go-zero读取请求体出现EOF错误的解决方法

    go-zero读取请求体出现EOF错误的解决方法

    这篇文章主要为大家详细介绍了go-zero读取请求体出现EOF错误时如何解决,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-02-02
  • 在Golang中使用iota案例详解

    在Golang中使用iota案例详解

    在Go语言中,iota是一个预定义的标识符,用于在常量声明中生成连续的递增值,iota的值从0开始,每次在常量声明中使用时递增,本就给大家讲解一下Golang中iota的使用案例,感兴趣的同学跟着小编一起来看看吧
    2023-07-07
  • goland 设置project gopath的操作

    goland 设置project gopath的操作

    这篇文章主要介绍了goland 设置project gopath的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • Golang全局变量加锁的问题解决

    Golang全局变量加锁的问题解决

    这篇文章主要介绍了解决Golang全局变量加锁的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • 一文详解Golang 定时任务库 gron 设计和原理

    一文详解Golang 定时任务库 gron 设计和原理

    这篇文章主要介绍了一文详解Golang 定时任务库 gron 设计和原理,gron是一个比较小巧、灵活的定时任务库,可以执行定时的、周期性的任务。gron提供简洁的、并发安全的接口
    2022-08-08
  • Golang实现按行读取文件的方法小结

    Golang实现按行读取文件的方法小结

    按行读取文件相较于一次性载入,有着很多优势,如内存效率高、处理速度快、实时性高等,本文主要介绍了Golang按行读取文件的相关方法,希望对大家有所帮助
    2024-02-02
  • golang中beego入门

    golang中beego入门

    Beego是一个基于Go语言的开源框架,用于构建Web应用程序和API,本文主要介绍了golang中beego入门,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • go并发编程sync.Cond使用场景及实现原理

    go并发编程sync.Cond使用场景及实现原理

    这篇文章主要为大家介绍了go并发编程sync.Cond使用场景及实现原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • 使用Go添加HTTPS的实现代码示例

    使用Go添加HTTPS的实现代码示例

    这篇文章主要介绍了使用Go添加HTTPS的实现代码示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • go build和go install的区别介绍

    go build和go install的区别介绍

    这篇文章主要介绍了go build和go install的区别介绍,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12

最新评论