成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

在Go編程中調用外部命令的幾種場景

開發 后端
在Go的標準庫中, 專門提供了os/exec包來對調用外部程序提供支持, 本文將對調用外部命令常用的幾種場景進行總結。

在很多場合, 使用Go語言需要調用外部命令來完成一些特定的任務, 例如: 使用Go語言調用Linux命令來獲取執行的結果,又或者調用第三方程序執行來完成額外的任務。在go的標準庫中, 專門提供了os/exec包來對調用外部程序提供支持, 本文將對調用外部命令常用的幾種場景進行總結。

直接調用函數

先用Linux上的一個簡單命令執行看一下效果, 執行cal命令, 會打印當前月的日期信息,如圖:

如果要使用Go代碼調用該命令, 可以使用以下代碼:

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

首先, 調用"os/exec"包中的Command函數,并傳入命令名稱作為參數, Command函數會返回一個exec.Cmd的命令對象。接著調用該命令對象的Run()方法運行命令。

如果此時運行程序, 會發現什么都沒有出現, 這是因為我們沒有處理標準輸出, 調用os/exec執行命令, 標準輸出和標準錯誤默認會被丟棄。

這里將cmd結構中的Stdout和Stderr分別設置為os.stdout和os.Stderr, 代碼如下:

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

運行程序后顯示:

輸出到文件

輸出到文件的關鍵, 是將exec.Cmd對象的Stdout和Stderr賦值文件句柄, 代碼如下:

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接口。

運行程序結果如下:

發送到網絡

這里開啟一個HTTP服務, 服務端接收兩個參數:年和月, 在服務端通過執行系統命令返回結果,代碼如下:

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 , 結果如下:

輸出到多個目標

如果要將執行命令的結果同時輸出到文件、網絡和內存對象, 可以使用io.MultiWriter滿足需求, io.MultiWriter可以很方便的將多個io.Writer轉換成一個io.Writer, 修改之前的Web服務端程序如下:

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)
}

分別獲取輸出內容和錯誤

這里我們封裝一個常用函數, 輸入接收命令和多個參數, 返回錯誤和命令返回信息, 函數代碼如下:

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()
}

該函數可以作為通用的命令執行返回結果的函數, 分別返回了錯誤和命令返回信息。

循環獲取命令內容

在Linux系統中,有些命令運行后結果是動態持續更新的,例如: top命令,對于該場景,我們封裝函數如下:

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()輸出管理函數, 我們可以實現持續獲取后臺命令返回的結果,并保持程序不退出。

在調用該函數的時候, 調用方式如下:

<-ExecCommandLoopTimeOutput("top")

打印出的信息將是一個持續顯示信息,如圖:

總結

本章節介紹了使用os/exec這個標準庫調用外部命令的各種場景。在實際應用中, 基本用的最多的還是封裝好的:ExecCommandOneTimeOutput()和ExecCommandLoopTimeOutput()兩個函數, 畢竟外部命令一般只會包含兩種:一種是執行后馬上獲取結果,第二種就是常駐內存持續獲取結果。

責任編輯:趙寧寧 來源: 二進制空間安全
相關推薦

2017-03-27 14:16:52

Vimshell命令

2017-11-27 09:11:42

SSDceph應用

2021-12-27 03:40:41

Go場景語言

2024-08-27 08:35:43

JavaScriptPromise模式

2019-08-28 09:04:02

Go語言Python操作系統

2024-04-16 12:13:07

usingC#開發

2020-01-14 11:17:33

Go并發Linux

2021-05-07 16:19:36

異步編程Java線程

2021-05-21 07:59:40

應用程序設計動態庫函數

2017-07-17 16:27:10

Docker Comp鏈接容器

2024-02-26 00:00:00

GoSocket編程

2014-09-23 14:17:31

Android圓形圖片

2011-06-19 08:59:59

錨文本

2024-03-19 14:15:48

Go程序os.Exit()

2021-08-02 11:13:28

人工智能機器學習技術

2024-02-21 08:33:27

GoReadDir性能

2020-07-24 08:04:18

Lambda

2021-11-10 15:18:16

JavaGo命令

2022-05-19 14:14:26

go語言限流算法

2018-01-16 15:42:38

Windows 10SSD磁盤
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲色片网站 | 夜夜av| 日韩视频区 | 欧美精品乱码久久久久久按摩 | 久久专区 | 一区二区三区四区不卡视频 | 天天爽网站 | 国产探花在线精品一区二区 | 亚洲视频在线一区 | 精品久久久久久久久久 | 国产日韩一区二区 | 先锋资源吧 | 日本午夜精品一区二区三区 | 亚洲欧洲精品一区 | 国产精品久久久久久久久久 | 特黄特黄a级毛片免费专区 av网站免费在线观看 | 久久天堂| 91影院在线观看 | 久久新视频 | 成人妇女免费播放久久久 | 中文字幕一区二区三区四区五区 | 日韩欧美综合 | 色久在线| 国产精品久久久久久久久久免费看 | 精品美女久久久 | 综合久久99 | 一区在线观看 | 久久亚洲一区二区 | 91影院 | 中文字幕亚洲欧美 | 久草院线 | 亚洲一区二区高清 | 久久久免费精品 | 最新国产精品 | 国产一级大片 | 欧美一级片免费看 | 成人在线黄色 | 国产日韩久久久久69影院 | 色伊人网 | 精品一区在线看 | 久久精品国产99国产精品亚洲 |