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

golang封裝一個執(zhí)行命令行的函數(shù)(return?stderr/stdout/exitcode)示例代碼

 更新時間:2024年06月27日 10:07:22   作者:happyblreay  
在?Go?語言中,您可以使用?os/exec?包來執(zhí)行外部命令,不通過調(diào)用?shell,并且能夠獲得進(jìn)程的退出碼、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤輸出,下面給大家分享golang封裝一個執(zhí)行命令行的函數(shù)(return?stderr/stdout/exitcode)的方法,感興趣的朋友跟隨小編一起看看吧

啟動shell來執(zhí)行命令行

在 Go 語言中,您可以使用 os/exec 包來執(zhí)行外部命令,不通過調(diào)用 shell,并且能夠獲得進(jìn)程的退出碼、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤輸出。下面是一個封裝好的函數(shù) runCommand,它符合您的需求:

package main
import (
	"bytes"
	"fmt"
	"os/exec"
)
// runCommand 函數(shù)接受一個命令行字符串,執(zhí)行它并返回退出碼、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤輸出
func runCommand(cmdline string) (exitCode int, stdout string, stderr string, err error) {
	// 解析命令行并準(zhǔn)備執(zhí)行
	cmd := exec.Command("sh", "-c", cmdline)
	var outBuffer, errBuffer bytes.Buffer
	cmd.Stdout = &outBuffer
	cmd.Stderr = &errBuffer
	// 執(zhí)行命令
	err = cmd.Run()
	stdout = outBuffer.String()
	stderr = errBuffer.String()
	// 獲取退出碼。如果命令執(zhí)行出錯,嘗試獲取退出碼
	if err != nil {
		if exitError, ok := err.(*exec.ExitError); ok {
			exitCode = exitError.ExitCode()
		} else {
			// 如果出現(xiàn)非 ExitError 類型錯誤,如執(zhí)行文件不存在或無執(zhí)行權(quán)限
			return 0, stdout, stderr, err
		}
	} else {
		// 命令成功執(zhí)行,退出碼為 0
		exitCode = 0
	}
	return exitCode, stdout, stderr, nil
}
func main() {
	// 測試 runCommand 函數(shù)
	exitCode, stdout, stderr, err := runCommand("ls -a")
	if err != nil {
		fmt.Printf("命令執(zhí)行出錯: %v\n", err)
	}
	fmt.Printf("退出碼: %d\n標(biāo)準(zhǔn)輸出: %s\n標(biāo)準(zhǔn)錯誤輸出: %s\n", exitCode, stdout, stderr)
}

這里的 runCommand 函數(shù)接受一個命令行字符串,執(zhí)行這條命令,并返回相關(guān)運(yùn)行結(jié)果。這個函數(shù)使用 exec.Command 來避免調(diào)用 shell。我們通過將命令傳給 sh-c 參數(shù),間接地執(zhí)行命令,但繞過了可執(zhí)行文件的正常尋找機(jī)制來防止 shell 注入問題。

結(jié)果輸出會分別寫入到 bytes.Buffer,這樣您就可以讀取并將其轉(zhuǎn)換為字符串。如果存在錯誤,且錯誤為 *exec.ExitError 類型,那么說明命令返回了非零退出碼,這時我們可以獲取并返回這個退出碼;如果是其他類型的錯誤,則直接返回錯誤。

這個函數(shù)的返回值包含了進(jìn)程的退出碼,標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤輸出的字符串表示,以及一個可能的錯誤值。如果命令成功執(zhí)行(即便其退出碼非零),則錯誤值為 nil。如果函數(shù)中出現(xiàn)了 Go 運(yùn)行時錯誤,比如命令不存在或無法啟動,那么會返回這個錯誤。

不啟動shell的方式

確實,前面的示例通過調(diào)用 sh 間接運(yùn)行命令,依然會啟動 shell。若要避免這種情況,我們會直接分解命令行字符串為命令名和參數(shù),然后不通過 shell 直接執(zhí)行這個命令。以下是經(jīng)過修改的 runCommand 函數(shù),它將使用 strings.Fields 來解析傳入的命令行字符串,并且不會啟動 shell。

package main
import (
	"bytes"
	"fmt"
	"os/exec"
	"strings"
)
// runCommand 函數(shù)接受一個命令行字符串,執(zhí)行它(無 shell 啟動)并返回退出碼、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤輸出
func runCommand(cmdline string) (exitCode int, stdout string, stderr string, err error) {
	// 使用 strings.Fields 解析命令行,分離出命令和參數(shù)
	args := strings.Fields(cmdline)
	if len(args) == 0 {
		return 0, "", "", fmt.Errorf("no command provided")
	}
	cmdName := args[0]
	cmdArgs := args[1:]
	// 準(zhǔn)備執(zhí)行不經(jīng)過 shell 的命令
	cmd := exec.Command(cmdName, cmdArgs...)
	var outBuffer, errBuffer bytes.Buffer
	cmd.Stdout = &outBuffer
	cmd.Stderr = &errBuffer
	// 執(zhí)行命令
	err = cmd.Run()
	stdout = outBuffer.String()
	stderr = errBuffer.String()
	// 獲取退出碼。如果命令執(zhí)行出錯,嘗試獲取退出碼
	if exitErr, ok := err.(*exec.ExitError); ok {
		err = nil // 清理錯誤,我們已經(jīng)獲取了退出碼
		exitCode = exitErr.ExitCode()
	} else if err != nil {
		// 如果出現(xiàn)非 ExitError 類型錯誤,如執(zhí)行文件不存在或無執(zhí)行權(quán)限
		exitCode = -1
	} else {
		// 命令成功執(zhí)行,退出碼為 0
		exitCode = 0
	}
	return exitCode, stdout, stderr, err
}
func main() {
	// 測試 runCommand 函數(shù)
	exitCode, stdout, stderr, err := runCommand("ls -a -l -h")
	if err != nil {
		fmt.Printf("命令執(zhí)行出錯: %v\n", err)
	}
	fmt.Printf("退出碼: %d\n標(biāo)準(zhǔn)輸出: %s\n標(biāo)準(zhǔn)錯誤輸出: %s\n", exitCode, stdout, stderr)
}

請注意,這個函數(shù)假設(shè)命令行參數(shù)不含有引號封閉的參數(shù)或其他需要 shell 解析的元素(如通配符 * 或重定向 >)。它簡單地把空白符作為參數(shù)分隔符,這是一個限制。如果你需要解析復(fù)雜的命令行字符串(包含引號或特殊字符),那么你需要一個更強(qiáng)大的解析器,或者需要以某種方式預(yù)處理命令行字符串。

因為直接執(zhí)行命令而不經(jīng)由 shell,原本在 shell 中利用的特性(如通配符展開、環(huán)境變量替換等)將不再可用。確保你的命令行字符串直接傳遞給系統(tǒng)調(diào)用是安全的。如果需要 shell 特性,那么你可能還需要調(diào)用 shell,但這正是你想要避免的。

關(guān)于類型斷言的表達(dá)式err.(*exec.ExitError)

在 Go 語言中, err.(*exec.ExitError) 是一個類型斷言的表達(dá)式。類型斷言用于檢查變量 err 是否為特定類型,或者能否轉(zhuǎn)換為特定類型。在這種情況下,類型斷言檢查 err 是否可以被斷言為 *exec.ExitError 類型。

exec.ExitErroros/exec 包中的一個結(jié)構(gòu)體類型,它實現(xiàn)了 error 接口,并包含了退出錯誤的相關(guān)信息。當(dāng)一個外部命令運(yùn)行結(jié)束并返回一個非零退出狀態(tài)時,os/exec 包的 RunWait 函數(shù)會返回一個 error 類型的值,這通常就是一個 *exec.ExitError 類型的實例。

一個類型斷言通常具有以下兩種形式:

  • x.(T):這種形式用于斷言變量 x 是否為類型 T。如果斷言成功,就會得到 x 的類型 T 的值。如果失敗,則會產(chǎn)生一個運(yùn)行時錯誤。因此,使用這種形式時必須非常確定 x 能夠斷言為類型 T
  • x, ok := x.(T):這種類型斷言形式比較安全,因為如果斷言失敗,它不會拋出錯誤,而是將 ok 的值設(shè)為 false,同時 x 的值會被設(shè)為類型 T 的零值。在你不確定 x 的類型是否為 T 或者你想要安全地檢查類型時,應(yīng)該使用這種形式。

在提供的代碼示例中,我們使用了第二種形式的類型斷言:

if exitErr, ok := err.(*exec.ExitError); ok {
    exitCode = exitErr.ExitCode()
    // ...
}

這里,我們嘗試將 errorerr 斷言為類型 *exec.ExitError。如果斷言成功(表示外部命令執(zhí)行失敗,并返回了一個非零退出代碼),變量 ok 的值將為 true,exitErr 將為 *exec.ExitError 類型,我們可以通過它的 ExitCode() 方法獲取實際的退出代碼。如果斷言失敗(err 不是 *exec.ExitError 類型),那么 okfalse,這通常表示 err 是另一種類型的錯誤或 nil。

到此這篇關(guān)于golang封裝一個執(zhí)行命令行的函數(shù)(return stderr/stdout/exitcode)的文章就介紹到這了,更多相關(guān)golang執(zhí)行命令行的函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go基礎(chǔ)系列:Go切片(分片)slice詳解

    Go基礎(chǔ)系列:Go切片(分片)slice詳解

    這篇文章主要介紹了Go語言中的切片(分片)slice詳細(xì)說明?,需要的朋友可以參考下
    2022-04-04
  • gin自定義中間件解決requestBody不可重讀(請求體取值)

    gin自定義中間件解決requestBody不可重讀(請求體取值)

    這篇文章主要介紹了gin自定義中間件解決requestBody不可重讀,確??刂破髂軌颢@取請求體值,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • 詳解Go中如何進(jìn)行進(jìn)行內(nèi)存優(yōu)化和垃圾收集器管理

    詳解Go中如何進(jìn)行進(jìn)行內(nèi)存優(yōu)化和垃圾收集器管理

    這篇文章主要為大家詳細(xì)介紹了Go中如何進(jìn)行進(jìn)行內(nèi)存優(yōu)化和垃圾收集器管理,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以了解下
    2023-11-11
  • Go Println和Printf的區(qū)別詳解

    Go Println和Printf的區(qū)別詳解

    這篇文章主要介紹了Go Println和Printf的區(qū)別詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • go語言程序cpu過高問題排查的方法詳解

    go語言程序cpu過高問題排查的方法詳解

    使用golang進(jìn)行復(fù)雜的組合運(yùn)算,導(dǎo)致CPU占用率非常高,下面這篇文章主要給大家介紹了關(guān)于go語言程序cpu過高問題排查的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • golang使用sync.singleflight解決熱點緩存穿透問題

    golang使用sync.singleflight解決熱點緩存穿透問題

    在go的sync包中,有一個singleflight包,里面有一個?singleflight.go文件,代碼加注釋,一共200行出頭,通過?singleflight可以很容易實現(xiàn)緩存和去重的效果,避免重復(fù)計算,接下來我們就給大家詳細(xì)介紹一下sync.singleflight如何解決熱點緩存穿透問題
    2023-07-07
  • Go語言基礎(chǔ)知識點介紹

    Go語言基礎(chǔ)知識點介紹

    在本篇文章里小編給大家整理的是一篇關(guān)于Go語言基礎(chǔ)知識點介紹內(nèi)容,有興趣的朋友們可以跟著學(xué)習(xí)參考下。
    2021-07-07
  • Go語言Grpc?Stream的實現(xiàn)

    Go語言Grpc?Stream的實現(xiàn)

    本文主要介紹了Go語言Grpc?Stream的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • goroutine?泄漏和避免泄漏實戰(zhàn)示例

    goroutine?泄漏和避免泄漏實戰(zhàn)示例

    這篇文章主要為大家介紹了goroutine?泄漏和避免泄漏實戰(zhàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Go語言基礎(chǔ)switch條件語句基本用法及示例詳解

    Go語言基礎(chǔ)switch條件語句基本用法及示例詳解

    這篇文章主要為大家介紹了Go語言基礎(chǔ)switch條件語句基本用法及示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-11-11

最新評論