欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語(yǔ)言執(zhí)行cmd命令庫(kù)的方法實(shí)現(xiàn)

 更新時(shí)間:2023年09月22日 09:11:14   作者:242030  
go語(yǔ)言用來(lái)執(zhí)行一個(gè)系統(tǒng)的命令相對(duì)python來(lái)說(shuō)還是有點(diǎn)復(fù)雜的,執(zhí)行命令是一個(gè)非常常見的需求,本文主要介紹了Go語(yǔ)言執(zhí)行cmd命令庫(kù)的方法實(shí)現(xiàn),感興趣的可以了解一下

有時(shí)候我們需要通過代碼的方式去執(zhí)行 linux 命令,那么 os/exec 這個(gè)系統(tǒng)庫(kù)剛好提供了相應(yīng)的功能。

Golang語(yǔ)言中提供了一個(gè) os/exec 包,它提供了一組函數(shù)和結(jié)構(gòu),用于調(diào)用外部程序,這些外部程序可以是系統(tǒng)

自帶的,也可以是用戶自定義的。os/exec 包中提供了一組函數(shù),用于執(zhí)行系統(tǒng)命令,我們可以使用它來(lái)執(zhí)行系

統(tǒng)的cmd命令行。

exec包執(zhí)行外部命令,它將 os.StartProcess 進(jìn)行包裝使得它更容易映射到 stdin 和 stdout,并且利用 pipe 連接i/o。

參考文檔:https://pkg.go.dev/os/exec

1、Command方法

func Command(name string, arg ...string) *Cmd {}

使用 exec.Command 函數(shù)來(lái)創(chuàng)建一個(gè) Cmd 結(jié)構(gòu)體,該函數(shù)接受兩個(gè)參數(shù),第一個(gè)參數(shù)是要執(zhí)行的命令,第二個(gè)

參數(shù)是命令行參數(shù),比如 ls -l,那么第一個(gè)參數(shù)就是 ls,第二個(gè)參數(shù)就是 -l。

2、Run方法

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

使用 Run 函數(shù)來(lái)執(zhí)行這個(gè)命令,Run 函數(shù)會(huì)根據(jù)我們傳入的參數(shù)來(lái)執(zhí)行命令,并返回一個(gè) error 類型的結(jié)果。

3、Output方法

可以使用 Output 函數(shù)來(lái)獲取命令執(zhí)行的結(jié)果。

4、簡(jiǎn)單例子

package main
import (
	"fmt"
	"os/exec"
)
func main() {
	// 創(chuàng)建一個(gè)Cmd結(jié)構(gòu)體
	cmd := exec.Command("ls", "-l", "/opt/software/")
	// // 不需要cmd.Run()
	out, err := cmd.Output()
	if err != nil {
		fmt.Println("執(zhí)行命令出錯(cuò): ", err)
		return
	} else {
		fmt.Println("獲取命令執(zhí)行結(jié)果: ", string(out))
	}
}
# 程序輸出
獲取命令執(zhí)行結(jié)果:  總用量 0
-rw-r--r--. 1 root root 0 5月  19 09:27 aa.txt
-rw-r--r--. 1 root root 0 5月  19 09:27 bb.txt
-rw-r--r--. 1 root root 0 5月  19 09:27 cc.txt
package main
import (
	"bytes"
	"fmt"
	"os/exec"
)
func main() {
	// 創(chuàng)建一個(gè)Cmd結(jié)構(gòu)體
	cmd := exec.Command("ls", "-l", "/opt/software/")
	// 設(shè)置輸出
	var stdout bytes.Buffer
	cmd.Stdout = &stdout
	// 執(zhí)行命令
	err := cmd.Run()
	if err != nil {
		fmt.Println("執(zhí)行命令出錯(cuò): ", err)
		return
	} else {
		fmt.Println("獲取命令執(zhí)行結(jié)果: ", stdout.String())
	}
}
# 程序輸出
獲取命令執(zhí)行結(jié)果:  總用量 0
-rw-r--r--. 1 root root 0 5月  19 09:27 aa.txt
-rw-r--r--. 1 root root 0 5月  19 09:27 bb.txt
-rw-r--r--. 1 root root 0 5月  19 09:27 cc.txt

5、查找cmd命令的可執(zhí)行二進(jìn)制文件

LookPath 在環(huán)境變量中查找科執(zhí)行二進(jìn)制文件,如果file中包含一個(gè)斜杠,則直接根據(jù)絕對(duì)路徑或者相對(duì)本目錄

的相對(duì)路徑去查找。

package main
import (
	"fmt"
	"os/exec"
)
func main() {
	f, err := exec.LookPath("ls")
	if err != nil {
		fmt.Println(err)
	}
	// /usr/bin/ls
	fmt.Println(f)
}

6、對(duì)標(biāo)準(zhǔn)輸入執(zhí)行cmd命令

package main
import (
	"bytes"
	"fmt"
	"os/exec"
	"strings"
	"log"
)
func main() {  
	// 進(jìn)行字符串的替換
	cmd := exec.Command("tr", "a-z", "A-Z")
	cmd.Stdin = strings.NewReader("some input")  
	var out bytes.Buffer  
	cmd.Stdout = &out  
	err := cmd.Run()  
	if err != nil {  
		log.Fatal(err)  
	}  
	// in all caps: SOME INPUT
	fmt.Printf("in all caps: %s\n", out.String())
}

7、標(biāo)準(zhǔn)輸出Output和CombinedOutput

// 運(yùn)行命令,并返回標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤
func (c *Cmd) CombinedOutput() ([]byte, error)
 //運(yùn)行命令并返回其標(biāo)準(zhǔn)輸出
 func (c *Cmd) Output() ([]byte, error)

注意:Output() 和 CombinedOutput() 不能夠同時(shí)使用,因?yàn)?command 的標(biāo)準(zhǔn)輸出只能有一個(gè),同時(shí)使用的話

便會(huì)定義了兩個(gè),便會(huì)報(bào)錯(cuò)。

package main
import (
	"fmt"
	"os/exec"
)
func main() {
	cmd := exec.Command("ls", "-l", "/opt/software/")
	out, err := cmd.CombinedOutput()
	if err != nil {
		fmt.Println(err) 
	}
	fmt.Println(string(out))  
}
$ go run 005.go 
total 0
-rw-r--r--. 1 root root 0 Jun 16 20:55 aa.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 bb.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 cc.txt
package main
import (
	"fmt"
	"os/exec"
)
func main() {  
    cmd := exec.Command("ls", "-l", "/opt/software/")
    out, err := cmd.Output()  
    if err != nil {  
        fmt.Println(err)  
    }  
    fmt.Println(string(out))  
}
$ go run 006.go 
total 0
-rw-r--r--. 1 root root 0 Jun 16 20:55 aa.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 bb.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 cc.txt

8、執(zhí)行命令Run和Start

// 開始指定命令并且等待它執(zhí)行結(jié)束,如果命令能夠成功執(zhí)行完畢,則返回nil,否則的話邊會(huì)產(chǎn)生錯(cuò)誤
func (c *Cmd) Run() error
// 使某個(gè)命令開始執(zhí)行,但是并不等到他執(zhí)行結(jié)束,這點(diǎn)和Run命令有區(qū)別,然后使用Wait方法等待命令執(zhí)行完畢并且釋放響應(yīng)的資源        
func (c *Cmd) Start() error          

注:一個(gè) command 只能使用 Start() 或者 Run() 中的一個(gè)啟動(dòng)命令,不能兩個(gè)同時(shí)使用。

Start 執(zhí)行不會(huì)等待命令完成,Run會(huì)阻塞等待命令完成。

下面看一下兩個(gè)命令的區(qū)別:

package main
import (
	"log"
	"os/exec"
)
func main() {
	log.Println("start")
	cmd := exec.Command("sleep", "10")
	// 執(zhí)行到此處時(shí)會(huì)阻塞等待10秒
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}
	log.Println("end")
}
$ go run 007-1.go 
2023/06/17 08:21:51 start
2023/06/17 08:22:01 end
package main
import (
	"log"
	"os/exec"
)
func main() {
	log.Println("start")
	cmd := exec.Command("sleep", "10")
	// 如果用start則直接向后運(yùn)行
	err := cmd.Start()
	if err != nil {
		log.Fatal(err)
	}
	log.Println("end")
	// 執(zhí)行Start會(huì)在此處等待10秒
	err = cmd.Wait()
	if err != nil {
		log.Fatal(err)
	}
	log.Println("wait")
}
$ go run 007-2.go 
2023/06/17 08:23:53 start
2023/06/17 08:23:53 end
2023/06/17 08:24:03 wait

9、管道Pipe

// StderrPipe返回一個(gè)pipe,這個(gè)管道連接到command的標(biāo)準(zhǔn)錯(cuò)誤,當(dāng)command命令退出時(shí),wait將關(guān)閉這些pipe
func (c *Cmd) StderrPipe() (io.ReadCloser, error)
// StdinPipe返回一個(gè)連接到command標(biāo)準(zhǔn)輸入的管道pipe
func (c *Cmd) StdinPipe() (io.WriteCloser, error)
// StdoutPipe返回一個(gè)連接到command標(biāo)準(zhǔn)輸出的管道pipe
func (c *Cmd) StdoutPipe() (io.ReadCloser, error)
package main
import (
	"fmt"
	"os"
	"os/exec"
)
func main() {
	cmd := exec.Command("cat")
	stdin, err := cmd.StdinPipe()
	if err != nil {
		fmt.Println(err)
	}
	_, err = stdin.Write([]byte("tmp.txt"))
	if err != nil {
		fmt.Println(err)
	}
	stdin.Close()
	// 終端標(biāo)準(zhǔn)輸出tmp.txt
	cmd.Stdout = os.Stdout
}
$ go run 008.go
tmp.txt
package main
import (
	"io/ioutil"
	"log"
	"os/exec"
)
func main() {
	cmd := exec.Command("ls", "-l", "/opt/software/")
	// 獲取輸出對(duì)象,可以從該對(duì)象中讀取輸出結(jié)果
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	// 保證關(guān)閉輸出流
	defer stdout.Close()
	// 運(yùn)行命令
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}
	// 讀取輸出結(jié)果
	if opBytes, err := ioutil.ReadAll(stdout); err != nil {
		log.Fatal(err)
	} else {
		log.Println(string(opBytes))
	}
	if err := cmd.Wait(); err != nil {
		log.Fatal(err)
	}
}
$ go run 009.go
total 0
-rw-r--r--. 1 root root 0 Jun 16 20:55 aa.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 bb.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 cc.txt

10、將命令的輸出結(jié)果重定向到文件中

package main
import (
	"log"
	"os"
	"os/exec"
)
func main() {
	cmd := exec.Command("ls", "-l", "/opt/software/")
	stdout, err := os.OpenFile("stdout.log", os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		log.Fatalln(err)
	}
	defer stdout.Close()
	// 重定向標(biāo)準(zhǔn)輸出到文件
	cmd.Stdout = stdout
	// 執(zhí)行命令
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}
	if err := cmd.Wait(); err != nil {
		log.Fatal(err)
	}
}
# 查看生成的文件的內(nèi)容
total 0
-rw-r--r--. 1 root root 0 Jun 16 20:55 aa.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 bb.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 cc.txt

11、Wait

// Wait等待command退出,它必須和Start一起使用,如果命令能夠順利執(zhí)行完并順利退出則返回nil,否則的話便會(huì)返回error,其中Wait會(huì)是放掉所有與cmd命令相關(guān)的資源
func (c *Cmd) Wait() error
package main
import (
	"io/ioutil"
	"log"
	"os/exec"
)
func main() {
	cmd := exec.Command("ls", "-l", "/opt/software/")
	// 指向cmd命令的stdout
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	defer stdout.Close()
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}
	if opBytes, err := ioutil.ReadAll(stdout); err != nil {
		log.Fatal(err)
	} else {
		log.Println(string(opBytes))
	}
	if err := cmd.Wait(); err != nil {
		log.Fatal(err)
	}
}
$ go run 011.go 
total 0
-rw-r--r--. 1 root root 0 Jun 16 20:55 aa.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 bb.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 cc.txt
package main
import (
	"encoding/json"
	"fmt"
	"log"
	"os/exec"
)
func main() {
	cmd := exec.Command("echo", "-n", `{"Name": "Bob", "Age": 32}`)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}
	var person struct {
		Name string
		Age  int
	}
	if err := json.NewDecoder(stdout).Decode(&person); err != nil {
		log.Fatal(err)
	}
	if err := cmd.Wait(); err != nil {
		log.Fatal(err)
	}
	// Bob is 32 years old
	fmt.Printf("%s is %d years old\n", person.Name, person.Age)
}

12、執(zhí)行過程中想要?dú)⑺纁md的執(zhí)行

package main
import (
	"context"
	"fmt"
	"log"
	"os/exec"
	"time"
)
func main() {
	log.Println("start")
	CanKillRun()
	log.Println("end")
}
// 執(zhí)行完發(fā)揮的數(shù)據(jù)結(jié)構(gòu)
type result struct {
	err    error
	output []byte
}
// 能夠殺死的進(jìn)程
func CanKillRun() {
	var (
		cmd        *exec.Cmd
		ctx        context.Context
		cancelFunc context.CancelFunc
		resultChan chan *result
		res        *result
	)
	// 創(chuàng)建一個(gè)通道用戶協(xié)程交換數(shù)據(jù)
	resultChan = make(chan *result, 1000)
	// 拿到這個(gè)上下文的取消方法
	ctx, cancelFunc = context.WithCancel(context.TODO())
	// 起一個(gè)goroutine可以理解是子進(jìn)程去處理
	go func() {
		var (
			output []byte
			err    error
		)
		cmd = exec.CommandContext(ctx, "bash", "-c", "sleep 3;echo hello;")
		// 執(zhí)行任務(wù),捕捉輸出
		output, err = cmd.CombinedOutput()
		// 把任務(wù)執(zhí)行結(jié)果輸出給main協(xié)程
		resultChan <- &result{
			err:    err,
			output: output,
		}
	}()
	// 1s后我們就把他殺死
	// 繼續(xù)往下走
	time.Sleep(1 * time.Second)
	// 取消上下文
	cancelFunc()
	// 讀取通道里面的數(shù)據(jù)
	res = <-resultChan
	// 打印結(jié)果
	fmt.Println("err: ", res.err, " out: ", string(res.output))
}
$ go run 013.go 
2023/06/17 08:36:52 start
err:  signal: killed  out:  
2023/06/17 08:36:55 end

13、執(zhí)行腳本并獲取結(jié)果

package main
import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"
)
/*
test.sh腳本內(nèi)容
#!/bin/bash
for k in $( seq 1 10 )
do
   echo "Hello World $k"
   sleep 1
done
*/
var contentArray = make([]string, 0, 5)
func main() {
	command := "/bin/bash"
	params := []string{"-c", "sh test.sh"}
	execCommand(command, params)
}
func execCommand(commandName string, params []string) bool {
	contentArray = contentArray[0:0]
	cmd := exec.Command(commandName, params...)
	// 顯示運(yùn)行的命令
	fmt.Printf("執(zhí)行命令: %s\n", strings.Join(cmd.Args, " "))
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Fprintln(os.Stderr, "error=>", err.Error())
		return false
	}
	// Start開始執(zhí)行包含的命令,但并不會(huì)等待該命令完成即返回
	// wait方法會(huì)返回命令的返回狀態(tài)碼并在命令返回后釋放相關(guān)的資源
	cmd.Start()
	reader := bufio.NewReader(stdout)
	var index int
	// 實(shí)時(shí)循環(huán)讀取輸出流中的一行內(nèi)容
	for {
		line, err2 := reader.ReadString('\n')
		if err2 != nil || io.EOF == err2 {
			break
		}
		fmt.Println(line)
		index++
		contentArray = append(contentArray, line)
	}
	cmd.Wait()
	return true
}
$ go run 014.go 
執(zhí)行命令: /bin/bash -c sh test.sh
Hello World 1
Hello World 2
Hello World 3
Hello World 4
Hello World 5
Hello World 6
Hello World 7
Hello World 8
Hello World 9
Hello World 10

 到此這篇關(guān)于Go語(yǔ)言執(zhí)行cmd命令庫(kù)的方法實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Go執(zhí)行cmd內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • GoFrame框架數(shù)據(jù)校驗(yàn)之校驗(yàn)結(jié)果Error接口對(duì)象

    GoFrame框架數(shù)據(jù)校驗(yàn)之校驗(yàn)結(jié)果Error接口對(duì)象

    這篇文章主要為大家介紹了GoFrame框架數(shù)據(jù)校驗(yàn)之校驗(yàn)結(jié)果Error接口對(duì)象示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Go語(yǔ)言包管理模式示例分析

    Go語(yǔ)言包管理模式示例分析

    這篇文章主要為大家介紹了Go語(yǔ)言包管理模式示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • Golang?rabbitMQ生產(chǎn)者消費(fèi)者實(shí)現(xiàn)示例

    Golang?rabbitMQ生產(chǎn)者消費(fèi)者實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了Golang?rabbitMQ生產(chǎn)者消費(fèi)者實(shí)現(xiàn)的示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • Go語(yǔ)言遍歷循環(huán)的幾種方法

    Go語(yǔ)言遍歷循環(huán)的幾種方法

    遍歷循環(huán)主要用于迭代數(shù)組、切片、映射(map)、字符串等數(shù)據(jù)結(jié)構(gòu),本文主要介紹了Go語(yǔ)言遍歷循環(huán)的幾種方法,下面就來(lái)介紹一下,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-03-03
  • Go語(yǔ)言設(shè)計(jì)模式之實(shí)現(xiàn)觀察者模式解決代碼臃腫

    Go語(yǔ)言設(shè)計(jì)模式之實(shí)現(xiàn)觀察者模式解決代碼臃腫

    今天學(xué)習(xí)一下用?Go?實(shí)現(xiàn)觀察者模式,觀察者模式主要是用來(lái)實(shí)現(xiàn)事件驅(qū)動(dòng)編程。事件驅(qū)動(dòng)編程的應(yīng)用還是挺廣的,除了我們都知道的能夠用來(lái)解耦:用戶修改密碼后,給用戶發(fā)短信進(jìn)行風(fēng)險(xiǎn)提示之類的典型場(chǎng)景,在微服務(wù)架構(gòu)實(shí)現(xiàn)最終一致性、實(shí)現(xiàn)事件源A?+?ES
    2022-08-08
  • 淺談Go數(shù)組比切片好在哪

    淺談Go數(shù)組比切片好在哪

    Go1.17 會(huì)正式支持切片轉(zhuǎn)換到數(shù)據(jù),不再需要用以前那種騷辦法了,本文就談?wù)凣o數(shù)組比切片好在哪,感興趣的可以了解一下
    2021-09-09
  • Go語(yǔ)言實(shí)現(xiàn)二分查找方法示例

    Go語(yǔ)言實(shí)現(xiàn)二分查找方法示例

    這篇文章主要為大家介紹了Go語(yǔ)言實(shí)現(xiàn)二分查找方法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • 使用go語(yǔ)言解析xml的實(shí)現(xiàn)方法(必看篇)

    使用go語(yǔ)言解析xml的實(shí)現(xiàn)方法(必看篇)

    下面小編就為大家?guī)?lái)一篇使用go語(yǔ)言解析xml的實(shí)現(xiàn)方法(必看篇)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2017-06-06
  • Go語(yǔ)言為什么很少使用數(shù)組原理解析

    Go語(yǔ)言為什么很少使用數(shù)組原理解析

    這篇文章主要為大家介紹了Go語(yǔ)言為什么很少使用數(shù)組原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • golang中字符串MD5生成方式總結(jié)

    golang中字符串MD5生成方式總結(jié)

    在本篇文章里小編給大家整理的是一篇關(guān)于golang中字符串MD5生成方式總結(jié)內(nèi)容,有興趣的朋友們可以跟著學(xué)習(xí)參考下。
    2021-07-07

最新評(píng)論