当前位置:首页 > 科技  > 软件

在Go编程中调用外部命令的几种场景

来源: 责编: 时间:2024-01-10 09:36:04 152观看
导读在很多场合, 使用Go语言需要调用外部命令来完成一些特定的任务, 例如: 使用Go语言调用Linux命令来获取执行的结果,又或者调用第三方程序执行来完成额外的任务。在go的标准库中, 专门提供了os/exec包来对调用外部程序

在很多场合, 使用Go语言需要调用外部命令来完成一些特定的任务, 例如: 使用Go语言调用Linux命令来获取执行的结果,又或者调用第三方程序执行来完成额外的任务。在go的标准库中, 专门提供了os/exec包来对调用外部程序提供支持, 本文将对调用外部命令常用的几种场景进行总结。atd28资讯网——每日最新资讯28at.com

atd28资讯网——每日最新资讯28at.com

直接调用函数

先用Linux上的一个简单命令执行看一下效果, 执行cal命令, 会打印当前月的日期信息,如图:atd28资讯网——每日最新资讯28at.com

atd28资讯网——每日最新资讯28at.com

如果要使用Go代码调用该命令, 可以使用以下代码:atd28资讯网——每日最新资讯28at.com

func main(){  cmd := exec.Command("cal")  err := cmd.Run()  if err != nil {     fmt.Println(err.Error())  }}

首先, 调用"os/exec"包中的Command函数,并传入命令名称作为参数, Command函数会返回一个exec.Cmd的命令对象。接着调用该命令对象的Run()方法运行命令。atd28资讯网——每日最新资讯28at.com

如果此时运行程序, 会发现什么都没有出现, 这是因为我们没有处理标准输出, 调用os/exec执行命令, 标准输出和标准错误默认会被丢弃。atd28资讯网——每日最新资讯28at.com

这里将cmd结构中的Stdout和Stderr分别设置为os.stdout和os.Stderr, 代码如下:atd28资讯网——每日最新资讯28at.com

func main(){    cmd := exec.Command("cal")    cmd.Stdout = os.Stdout    cmd.Stderr = os.Stderr    err := cmd.Run()    if err != nil {      fmt.Println(err.Error())    }}

运行程序后显示:atd28资讯网——每日最新资讯28at.com

atd28资讯网——每日最新资讯28at.com

输出到文件

输出到文件的关键, 是将exec.Cmd对象的Stdout和Stderr赋值文件句柄, 代码如下:atd28资讯网——每日最新资讯28at.com

func main(){    f, err := os.OpenFile("sample.txt", os.O_WRONLY|os.O_CREATE, os.ModePerm)    if err != nil {      fmt.Println(err.Error())    }    cmd := exec.Command("cal")    cmd.Stdout = f    cmd.Stderr = f    err := cmd.Run()    if err != nil {      fmt.Println(err.Error())    }}

os.OpenFile打开一个文件, 指定os.0_CREATE标志让操作系统在文件不存在时自动创建, 返回文件对象*os.File, *os.File实现了io.Writer接口。atd28资讯网——每日最新资讯28at.com

运行程序结果如下:atd28资讯网——每日最新资讯28at.com

atd28资讯网——每日最新资讯28at.com

发送到网络

这里开启一个HTTP服务, 服务端接收两个参数:年和月, 在服务端通过执行系统命令返回结果,代码如下:atd28资讯网——每日最新资讯28at.com

import (  "fmt"  "net/http"  "os/exec")func queryDate(w http.ResponseWriter, r *http.Request) {  var err error  if r.Method == "GET" {    year := r.URL.Query().Get("year")    month := r.URL.Query().Get("month")    cmd := exec.Command("cal", month, year)    cmd.Stdout = w    cmd.Stderr = w    err = cmd.Run()    if err != nil {      fmt.Println(err.Error())    }  }}func main() {  http.HandleFunc("/querydate", queryDate)  http.ListenAndServe(":8001", nil)}

打开浏览器,在地址栏中输入URL查询2023年10月份的日历:http://localhost:8001/querydate?year=2023&mnotallow=10 , 结果如下:atd28资讯网——每日最新资讯28at.com

atd28资讯网——每日最新资讯28at.com

输出到多个目标

如果要将执行命令的结果同时输出到文件、网络和内存对象, 可以使用io.MultiWriter满足需求, io.MultiWriter可以很方便的将多个io.Writer转换成一个io.Writer, 修改之前的Web服务端程序如下:atd28资讯网——每日最新资讯28at.com

func queryDate(w http.ResponseWriter, r *http.Request) {  var err error  if r.Method == "GET" {    buffer := bytes.NewBuffer(nil)    year := r.URL.Query().Get("year")    month := r.URL.Query().Get("month")    f, _ := os.OpenFile("sample.txt", os.O_WRONLY|os.O_CREATE, os.ModePerm)    mw := io.MultiWriter(w, f, buffer)    cmd := exec.Command("cal", month, year)    cmd.Stdout = mw    cmd.Stderr = mw    err = cmd.Run()    if err != nil {      fmt.Println(err.Error())    }    fmt.Println(buffer.String())  }}func main() {  http.HandleFunc("/querydate", queryDate)  http.ListenAndServe(":8001", nil)}

分别获取输出内容和错误

这里我们封装一个常用函数, 输入接收命令和多个参数, 返回错误和命令返回信息, 函数代码如下:atd28资讯网——每日最新资讯28at.com

func ExecCommandOneTimeOutput(name string, args ...string) (error, string) {  var out bytes.Buffer  var stderr bytes.Buffer  cmd := exec.Command(name, args...)  cmd.Stdout = &out  cmd.Stderr = &stderr  err := cmd.Run()  if err != nil {    fmt.Println(fmt.Sprint(err) + ": " + stderr.String())    return err, ""  }  return nil, out.String()}

该函数可以作为通用的命令执行返回结果的函数, 分别返回了错误和命令返回信息。atd28资讯网——每日最新资讯28at.com

循环获取命令内容

在Linux系统中,有些命令运行后结果是动态持续更新的,例如: top命令,对于该场景,我们封装函数如下:atd28资讯网——每日最新资讯28at.com

func ExecCommandLoopTimeOutput(name string, args ...string) <-chan struct{} {  cmd := exec.Command(name, args...)  closed := make(chan struct{})  defer close(closed)  stdoutPipe, err := cmd.StdoutPipe()  if err != nil {    fmt.Println(err.Error())  }  defer stdoutPipe.Close()  go func() {    scanner := bufio.NewScanner(stdoutPipe)    for scanner.Scan() {      fmt.Println(string(scanner.Bytes()))      _, err := simplifiedchinese.GB18030.NewDecoder().Bytes(scanner.Bytes())      if err != nil {        continue      }    }  }()  if err := cmd.Run(); err != nil {    fmt.Println(err.Error())  }  return closed}

通过调用cmd对象的StdoutPipe()输出管理函数, 我们可以实现持续获取后台命令返回的结果,并保持程序不退出。atd28资讯网——每日最新资讯28at.com

在调用该函数的时候, 调用方式如下:atd28资讯网——每日最新资讯28at.com

<-ExecCommandLoopTimeOutput("top")

打印出的信息将是一个持续显示信息,如图:atd28资讯网——每日最新资讯28at.com

atd28资讯网——每日最新资讯28at.com

总结

本章节介绍了使用os/exec这个标准库调用外部命令的各种场景。在实际应用中, 基本用的最多的还是封装好的:ExecCommandOneTimeOutput()和ExecCommandLoopTimeOutput()两个函数, 毕竟外部命令一般只会包含两种:一种是执行后马上获取结果,第二种就是常驻内存持续获取结果。atd28资讯网——每日最新资讯28at.com

atd28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-59680-0.html在Go编程中调用外部命令的几种场景

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 全网最详细MVCC讲解,一篇看懂

下一篇: Rust真慢,差点跟同事打起来

标签:
  • 热门焦点
  • 6月iOS设备好评榜:第一蝉联榜首近一年

    6月iOS设备好评榜:第一蝉联榜首近一年

    作为安兔兔各种榜单里变化最小的那个,2023年6月的iOS好评榜和上个月相比没有任何排名上的变化,仅仅是部分设备好评率的下降,长年累月的用户评价和逐渐退出市场的老款机器让这
  • 从零到英雄:高并发与性能优化的神奇之旅

    从零到英雄:高并发与性能优化的神奇之旅

    作者 | 波哥审校 | 重楼作为公司的架构师或者程序员,你是否曾经为公司的系统在面对高并发和性能瓶颈时感到手足无措或者焦头烂额呢?笔者在出道那会为此是吃尽了苦头的,不过也得
  • “又被陈思诚骗了”

    “又被陈思诚骗了”

    作者|张思齐 出品|众面(ID:ZhongMian_ZM)如今的国产悬疑电影,成了陈思诚的天下。最近大爆电影《消失的她》票房突破30亿断层夺魁暑期档,陈思诚再度风头无两。你可以说陈思诚的
  • 新电商三兄弟,“抖快红”成团!

    新电商三兄弟,“抖快红”成团!

    来源:价值研究所作 者:Hernanderz 随着内容电商的概念兴起,抖音、快手、小红书组成的&ldquo;新电商三兄弟&rdquo;成为业内一股不可忽视的势力,给阿里、京东、拼多多带去了巨大压
  • 年轻人的“职场羞耻感”,无处不在

    年轻人的“职场羞耻感”,无处不在

    作者:冯晓亭 陶 淘 李 欣 张 琳 马舒叶来源:燃次元&ldquo;人在职场,应该选择什么样的着装?&rdquo;近日,在网络上,一个与着装相关的帖子引发关注,在该帖子里,一位在高级写字楼亚洲金
  • 华为HarmonyOS 4.0将于8月4日发布 或搭载AI大模型技术

    华为HarmonyOS 4.0将于8月4日发布 或搭载AI大模型技术

    华为宣布HarmonyOS4.0将于8月4日正式发布。此前,华为已经针对开发者公布了HarmonyOS4.0,以便于开发者提前进行适配,也因此被曝光出了一些新系统的特性
  • 2299元起!iQOO Pad明晚首销:性能最强天玑平板

    2299元起!iQOO Pad明晚首销:性能最强天玑平板

    5月23日,iQOO如期举行了新品发布会,除了首发安卓最强旗舰处理器的iQOO Neo8系列新机外,还在发布会上推出了旗下首款平板电脑——iQOO Pad,其最大的卖点
  • 与兆芯合作  联想推出全新旗舰版笔记本电脑开天N7系列

    与兆芯合作 联想推出全新旗舰版笔记本电脑开天N7系列

    联想与兆芯合作推出全新联想旗舰版笔记本电脑开天 N7系列。这个系列采用兆芯KX-6640MA处理器平台,KX-6640MA 处理器是采用了陆家嘴架构,16nm 工艺,4 核 4 线
  • Meta盲目扩张致超万人被裁,重金押注元宇宙而前景未明

    Meta盲目扩张致超万人被裁,重金押注元宇宙而前景未明

    图片来源:图虫创意日前,Meta创始人兼CEO 马克&middot;扎克伯发布公开信,宣布Meta计划裁员超11000人,占其员工总数13%。他公开承认了自己的预判失误:&ldquo;不仅
Top