最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

啟動(dòng)shell來(lái)執(zhí)行命令行

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

package main
import (
	"bytes"
	"fmt"
	"os/exec"
)
// runCommand 函數(shù)接受一個(gè)命令行字符串,執(zhí)行它并返回退出碼、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出
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í)行出錯(cuò),嘗試獲取退出碼
	if err != nil {
		if exitError, ok := err.(*exec.ExitError); ok {
			exitCode = exitError.ExitCode()
		} else {
			// 如果出現(xiàn)非 ExitError 類(lèi)型錯(cuò)誤,如執(zhí)行文件不存在或無(wú)執(zhí)行權(quán)限
			return 0, stdout, stderr, err
		}
	} else {
		// 命令成功執(zhí)行,退出碼為 0
		exitCode = 0
	}
	return exitCode, stdout, stderr, nil
}
func main() {
	// 測(cè)試 runCommand 函數(shù)
	exitCode, stdout, stderr, err := runCommand("ls -a")
	if err != nil {
		fmt.Printf("命令執(zhí)行出錯(cuò): %v\n", err)
	}
	fmt.Printf("退出碼: %d\n標(biāo)準(zhǔn)輸出: %s\n標(biāo)準(zhǔn)錯(cuò)誤輸出: %s\n", exitCode, stdout, stderr)
}

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

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

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

不啟動(dòng)shell的方式

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

package main
import (
	"bytes"
	"fmt"
	"os/exec"
	"strings"
)
// runCommand 函數(shù)接受一個(gè)命令行字符串,執(zhí)行它(無(wú) shell 啟動(dòng))并返回退出碼、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出
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)過(guò) 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í)行出錯(cuò),嘗試獲取退出碼
	if exitErr, ok := err.(*exec.ExitError); ok {
		err = nil // 清理錯(cuò)誤,我們已經(jīng)獲取了退出碼
		exitCode = exitErr.ExitCode()
	} else if err != nil {
		// 如果出現(xiàn)非 ExitError 類(lèi)型錯(cuò)誤,如執(zhí)行文件不存在或無(wú)執(zhí)行權(quán)限
		exitCode = -1
	} else {
		// 命令成功執(zhí)行,退出碼為 0
		exitCode = 0
	}
	return exitCode, stdout, stderr, err
}
func main() {
	// 測(cè)試 runCommand 函數(shù)
	exitCode, stdout, stderr, err := runCommand("ls -a -l -h")
	if err != nil {
		fmt.Printf("命令執(zhí)行出錯(cuò): %v\n", err)
	}
	fmt.Printf("退出碼: %d\n標(biāo)準(zhǔn)輸出: %s\n標(biāo)準(zhǔn)錯(cuò)誤輸出: %s\n", exitCode, stdout, stderr)
}

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

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

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

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

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

一個(gè)類(lèi)型斷言通常具有以下兩種形式:

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

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

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

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

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

相關(guān)文章

  • 一鍵定位Golang線(xiàn)上服務(wù)內(nèi)存泄露的秘籍

    一鍵定位Golang線(xiàn)上服務(wù)內(nèi)存泄露的秘籍

    內(nèi)存泄露?別讓它拖垮你的Golang線(xiàn)上服務(wù)!快速掌握Go語(yǔ)言服務(wù)內(nèi)存泄漏排查秘籍,從此問(wèn)題無(wú)處遁形,一文讀懂如何精準(zhǔn)定位與有效解決Golang應(yīng)用中的內(nèi)存問(wèn)題,立即閱讀,讓性能飛升!
    2024-01-01
  • go語(yǔ)言單例模式(Singleton)實(shí)例分析

    go語(yǔ)言單例模式(Singleton)實(shí)例分析

    這篇文章主要介紹了go語(yǔ)言單例模式(Singleton),實(shí)例分析了單例模式的原理與Go語(yǔ)言的實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2015-03-03
  • Go語(yǔ)言中的并發(fā)goroutine底層原理

    Go語(yǔ)言中的并發(fā)goroutine底層原理

    這篇文章主要介紹了Go語(yǔ)言中的并發(fā)goroutine底層原理,介紹Go語(yǔ)言并發(fā)底層原理,以及對(duì)比Go語(yǔ)言并發(fā)與其他語(yǔ)言并發(fā)的優(yōu)劣,下文詳細(xì)內(nèi)容,需要的小伙伴可以參考一下
    2022-02-02
  • Go實(shí)現(xiàn)文件上傳和下載

    Go實(shí)現(xiàn)文件上傳和下載

    這篇文章主要為大家詳細(xì)介紹了Go實(shí)現(xiàn)文件上傳和下載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • Go語(yǔ)言清除文件中空行的方法

    Go語(yǔ)言清除文件中空行的方法

    這篇文章主要介紹了Go語(yǔ)言清除文件中空行的方法,實(shí)例分析了Go語(yǔ)言針對(duì)文件的操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • Go語(yǔ)言實(shí)現(xiàn)AzDG可逆加密算法實(shí)例

    Go語(yǔ)言實(shí)現(xiàn)AzDG可逆加密算法實(shí)例

    這篇文章主要介紹了Go語(yǔ)言實(shí)現(xiàn)AzDG可逆加密算法,實(shí)例分析了AzDG可逆加密算法的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • Go并發(fā)調(diào)用的超時(shí)處理的方法

    Go并發(fā)調(diào)用的超時(shí)處理的方法

    這篇文章主要介紹了Go并發(fā)調(diào)用的超時(shí)處理的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • Golang中crypto/rand庫(kù)的使用技巧與最佳實(shí)踐

    Golang中crypto/rand庫(kù)的使用技巧與最佳實(shí)踐

    在Golang的眾多隨機(jī)數(shù)生成庫(kù)中,crypto/rand?是一個(gè)專(zhuān)為加密安全設(shè)計(jì)的庫(kù),本文主要介紹了Golang中crypto/rand庫(kù)的使用技巧與最佳實(shí)踐,感興趣的可以了解一下
    2024-02-02
  • golang中context.WithValue的使用規(guī)范問(wèn)題小結(jié)

    golang中context.WithValue的使用規(guī)范問(wèn)題小結(jié)

    本文主要介紹了golang中context.WithValue的使用規(guī)范問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-02-02
  • Go高級(jí)特性探究之協(xié)程池詳解

    Go高級(jí)特性探究之協(xié)程池詳解

    在并發(fā)編程中,協(xié)程是?Go?語(yǔ)言的核心特性之一,本文將介紹如何使用?Go?協(xié)程池構(gòu)造一個(gè)協(xié)程池,并解決函數(shù)傳參問(wèn)題、優(yōu)雅關(guān)閉協(xié)程池和保證協(xié)程安全的問(wèn)題,感興趣的可以了解一下
    2023-06-06

最新評(píng)論

南溪县| 突泉县| 东光县| 九寨沟县| 勃利县| 永定县| 鄂尔多斯市| 阳原县| 东宁县| 昌吉市| 丁青县| 瓮安县| 荔浦县| 濮阳市| 高阳县| 长治县| 盐边县| 莱芜市| 岳普湖县| 克拉玛依市| 邵武市| 留坝县| 永州市| 黔西| 隆子县| 延津县| 奎屯市| 灵璧县| 阿坝县| 伊吾县| 弋阳县| 太仆寺旗| 竹山县| 汉阴县| 炎陵县| 普安县| 绥滨县| 垦利县| 炉霍县| 镇安县| 崇礼县|