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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一文彻底理解Golang闭包实现原理

    一文彻底理解Golang闭包实现原理

    闭包对于一个长期写Java的开发者来说估计鲜有耳闻,光这名字感觉就有点"神秘莫测"。这篇文章的主要目的就是从编译器的角度来分析闭包,彻底搞懂闭包的实现原理,需要的可以参考一下
    2022-10-10
  • Go语言学习教程之goroutine和通道的示例详解

    Go语言学习教程之goroutine和通道的示例详解

    这篇文章主要通过A Tour of Go中的例子进行学习,以此了解Go语言中的goroutine和通道,文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-09-09
  • Go语言编程通过dwarf获取内联函数

    Go语言编程通过dwarf获取内联函数

    这篇文章主要为大家介绍了Go语言编程通过dwarf获取内联函数详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • golang 归并排序,快速排序,堆排序的实现

    golang 归并排序,快速排序,堆排序的实现

    本文主要介绍了golang 归并排序,快速排序,堆排序的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • 大多数Go程序员都走过的坑盘点解析

    大多数Go程序员都走过的坑盘点解析

    这篇文章主要为大家介绍了大多数Go程序员都走过的坑盘点解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • golang中range在slice和map遍历中的注意事项

    golang中range在slice和map遍历中的注意事项

    今天小编就为大家分享一篇关于golang中range在slice和map遍历中的注意事项,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • go-cqhttp环境配置及安装过程

    go-cqhttp环境配置及安装过程

    这篇文章主要介绍了go-cqhttp环境配置,包括go-cqhttp安装及简单介绍,本文结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • Go并发编程中sync/errGroup的使用

    Go并发编程中sync/errGroup的使用

    本文主要介绍了Go并发编程中sync/errGroup的使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • Go读取配置文件的方法总结

    Go读取配置文件的方法总结

    我们常见的配置文件的格式一般有:XML、JSON、INI、YAML、env和.properties,本文小编为大家整理了Go语言读取这些格式的配置文件的方法,希望对大家有所帮助
    2023-10-10
  • Go学习笔记之Zap日志的使用

    Go学习笔记之Zap日志的使用

    这篇文章主要为大家详细介绍了Go语言中Zap日志的使用以及安装,文中的示例代码讲解详细,对我们学习Go语言有一定的帮助,需要的可以参考一下
    2022-07-07

最新评论