日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

golang中的shell

發(fā)布時間:2025/6/15 编程问答 7 豆豆
生活随笔 收集整理的這篇文章主要介紹了 golang中的shell 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

api

func (*Cmd) Run func (c *Cmd) Run() errorRun執(zhí)行c包含的命令,并阻塞直到完成。 如果命令成功執(zhí)行,stdin、stdout、stderr的轉交沒有問題,并且返回狀態(tài)碼為0,方法的返回值為nil;如果命令沒有執(zhí)行或者執(zhí)行失敗,會返回*ExitError類型的錯誤;否則返回的error可能是表示I/O問題。 func (*Cmd) Start func (c *Cmd) Start() errorStart開始執(zhí)行c包含的命令,但并不會等待該命令完成即返回。Wait方法會返回命令的返回狀態(tài)碼并在命令返回后釋放相關的資源。 func (*Cmd) Wait func (c *Cmd) Wait() error Wait會阻塞直到該命令執(zhí)行完成,該命令必須是被Start方法開始執(zhí)行的。如果命令成功執(zhí)行,stdin、stdout、stderr的轉交沒有問題,并且返回狀態(tài)碼為0,方法的返回值為nil;如果命令沒有執(zhí)行或者執(zhí)行失敗,會返回*ExitError類型的錯誤;否則返回的error可能是表示I/O問題。Wait方法會在命令返回后釋放相關的資源。 func (*Cmd) Output func (c *Cmd) Output() ([]byte, error) 執(zhí)行命令并返回標準輸出的切片。 func (*Cmd) StderrPipe func (c *Cmd) StderrPipe() (io.ReadCloser, error) StderrPipe方法返回一個在命令Start后與命令標準錯誤輸出關聯(lián)的管道。Wait方法獲知命令結束后會關閉這個管道,一般不需要顯式的關閉該管道。但是在從管道讀取完全部數(shù)據(jù)之前調(diào)用Wait是錯誤的;同樣使用StderrPipe方法時調(diào)用Run函數(shù)也是錯誤的。

阻塞方式(需要執(zhí)行結果)

主要用于執(zhí)行shell命令,并且返回shell的標準輸出

適用于執(zhí)行普通非阻塞shell命令,且需要shell標準輸出的

//阻塞式的執(zhí)行外部shell命令的函數(shù),等待執(zhí)行完畢并返回標準輸出 func exec_shell(s string) (string, error){//函數(shù)返回一個*Cmd,用于使用給出的參數(shù)執(zhí)行name指定的程序cmd := exec.Command("/bin/bash", "-c", s)//讀取io.Writer類型的cmd.Stdout,再通過bytes.Buffer(緩沖byte類型的緩沖器)將byte類型轉化為string類型(out.String():這是bytes類型提供的接口)var out bytes.Buffercmd.Stdout = &out//Run執(zhí)行c包含的命令,并阻塞直到完成。 這里stdout被取出,cmd.Wait()無法正確獲取stdin,stdout,stderr,則阻塞在那了err := cmd.Run()checkErr(err)return out.String(), err }

需要對shell標準輸出的逐行實時進行處理的

func execCommand(commandName string, params []string) bool {//函數(shù)返回一個*Cmd,用于使用給出的參數(shù)執(zhí)行name指定的程序cmd := exec.Command(commandName, params...)//顯示運行的命令fmt.Println(cmd.Args)//StdoutPipe方法返回一個在命令Start后與命令標準輸出關聯(lián)的管道。Wait方法獲知命令結束后會關閉這個管道,一般不需要顯式的關閉該管道。stdout, err := cmd.StdoutPipe()if err != nil {fmt.Println(err)return false}cmd.Start()//創(chuàng)建一個流來讀取管道內(nèi)內(nèi)容,這里邏輯是通過一行一行的讀取的reader := bufio.NewReader(stdout)//實時循環(huán)讀取輸出流中的一行內(nèi)容for {line, err2 := reader.ReadString('\n')if err2 != nil || io.EOF == err2 {break}fmt.Println(line)}//阻塞直到該命令執(zhí)行完成,該命令必須是被Start方法開始執(zhí)行的cmd.Wait()return true }

非阻塞方式(不需要執(zhí)行結果)

通過shell調(diào)用自己的程序,并且程序是死循環(huán),此時無法獲取返回結果(否則程序會一直阻塞直至調(diào)用的 程序結束)

適用于調(diào)用自己寫的程序(服務器死循環(huán),且不需要返回結果的)

//不需要執(zhí)行命令的結果與成功與否,執(zhí)行命令馬上就返回 func exec_shell_no_result(command string) {//處理啟動參數(shù),通過空格分離 如:setsid /home/luojing/gotest/src/test_main/iwatch/test/while_little &command_name_and_args := strings.FieldsFunc(command, splite_command)//開始執(zhí)行c包含的命令,但并不會等待該命令完成即返回cmd.Start()if err != nil {fmt.Printf("%v: exec command:%v error:%v\n", get_time(), command, err)}fmt.Printf("Waiting for command:%v to finish...\n", command)//阻塞等待fork出的子進程執(zhí)行的結果,和cmd.Start()配合使用[不等待回收資源,會導致fork出執(zhí)行shell命令的子進程變?yōu)榻┦M程]err = cmd.Wait()if err != nil {fmt.Printf("%v: Command finished with error: %v\n", get_time(), err)}return } /錯誤處理函數(shù) func checkErr(err error) {if err != nil {fmt.Println(err)panic(err) } }

ssh

go get golang.org/x/crypto/ssh

ssh執(zhí)行命令

這個方法需要有一個環(huán)境的準備:與目標服務器建立免密碼登陸],并且執(zhí)行程序的用戶與執(zhí)行用戶一致

import ("net""log""fmt""bytes""os/exec""strconv"str "strings""golang.org/x/crypto/ssh" )func runCmd(){var stdOut, stdErr bytes.Buffercmd := exec.Command( "ssh", "username@192.168.1.4", "if [ -d liujx/project ];then echo 0;else echo 1;fi" )cmd.Stdout = &stdOutcmd.Stderr = &stdErrif err := cmd.Run(); err != nil {fmt.Printf( "cmd exec failed: %s : %s", fmt.Sprint( err ), stdErr.String() )}fmt.Print( stdOut.String() )ret, err := strconv.Atoi( str.Replace( stdOut.String(), "\n", "", -1 ) )if err != nil {panic(err)}fmt.Printf("%d, %s\n", ret, stdErr.String() ) }

ssh客戶端連接

這種方法可以不用搭建免密碼登陸環(huán)境,連接時可指定用戶和密碼的

func SSHConnect( user, password, host string, port int ) ( *ssh.Session, error ) {var (auth []ssh.AuthMethodaddr stringclientConfig *ssh.ClientConfigclient *ssh.Clientsession *ssh.Sessionerr error)// get auth methodauth = make([]ssh.AuthMethod, 0)auth = append(auth, ssh.Password(password))hostKeyCallbk := func(hostname string, remote net.Addr, key ssh.PublicKey) error {return nil}clientConfig = &ssh.ClientConfig{User: user,Auth: auth,// Timeout: 30 * time.Second,HostKeyCallback: hostKeyCallbk, }// connet to sshaddr = fmt.Sprintf( "%s:%d", host, port )if client, err = ssh.Dial( "tcp", addr, clientConfig ); err != nil {return nil, err}// create sessionif session, err = client.NewSession(); err != nil {return nil, err}return session, nil }func runSsh(){var stdOut, stdErr bytes.Buffersession, err := SSHConnect( "username", "passworld", "192.168.1.4", 22 )if err != nil {log.Fatal(err)}defer session.Close()session.Stdout = &stdOutsession.Stderr = &stdErrsession.Run("if [ -d liujx/project ]; then echo 0; else echo 1; fi")ret, err := strconv.Atoi( str.Replace( stdOut.String(), "\n", "", -1 ) )if err != nil {panic(err)}fmt.Printf("%d, %s\n", ret, stdErr.String() )}

os.Args

func main() {osArg := os.Args //[]string/**o 開始,第一個是文件路徑*/for i, data := range osArg {fmt.Println(i, data)} }

flag命令行參數(shù)

每個處理一行

func main() {var recusive boolvar test stringvar level intflag.BoolVar(&recusive, "r", false, "recusive xxx")flag.StringVar(&test, "t","default string", "string option")flag.IntVar(&level, "l", 1, "level of xxx")flag.Parse()fmt.Println(recusive)fmt.Println(test)fmt.Println(level) }

不傳就給默認值

? studygo ./studygo false default string 1

傳遞就按照傳遞的來

? studygo ./studygo -r -t hello -l 11 true hello 11

urfave/cli框架

可以通過-h查看幫助

import ("fmt""github.com/urfave/cli""os" )func main() {var language stringvar recusive boolapp := cli.NewApp()//指定名字app.Name = "greet"app.Usage = "用法"app.Flags = []cli.Flag{cli.StringFlag{Name: "lang, l",Value: "english",Usage: "select language",Destination: &language,},cli.BoolFlag{Name: "recusive, r",Usage: "recusive for the greeting",Destination: &recusive,},}app.Action = func(c *cli.Context) error {var cmd string//如果用戶傳過來 >0if c.NArg() > 0 {cmd = c.Args()[0]fmt.Println("cmd is ", cmd)}fmt.Println("recusive is: ", recusive)fmt.Println("language is: ", language)return nil}app.Run(os.Args) }

啟動外部命令和程序

os 包有一個StartProcess函數(shù)可以調(diào)用或啟動外部系統(tǒng)命令和二進制可執(zhí)行文件;它的第一個參數(shù)是要運行的進程,第二個參數(shù)用來傳遞選項或參數(shù),第三個參數(shù)是含有系統(tǒng)環(huán)境基本信息的結構體。

這個函數(shù)返回被啟動進程的 id(pid),或者啟動失敗返回錯誤。

exec 包中也有同樣功能的更簡單的結構體和函數(shù);主要是exec.Command(name string, arg ...string)和Run()。首先需要用系統(tǒng)命令或可執(zhí)行文件的名字創(chuàng)建一個Command對象,然后用這個對象作為接收者調(diào)用Run()。下面的程序(因為是執(zhí)行 Linux 命令,只能在 Linux 下面運行)演示了它們的使用:

// exec.go package main import ("fmt""os/exec""os" )func main() { // 1) os.StartProcess // /*********************/ /* Linux: */ env := os.Environ() procAttr := &os.ProcAttr{Env: env,Files: []*os.File{os.Stdin,os.Stdout,os.Stderr,},} // 1st example: list files pid, err := os.StartProcess("/bin/ls", []string{"ls", "-l"}, procAttr) if err != nil {fmt.Printf("Error %v starting process!", err) //os.Exit(1) } fmt.Printf("The process id is %v", pid)

輸出:

The process id is &{2054 0}total 2056 -rwxr-xr-x 1 ivo ivo 1157555 2011-07-04 16:48 Mieken_exec -rw-r--r-- 1 ivo ivo 2124 2011-07-04 16:48 Mieken_exec.go -rw-r--r-- 1 ivo ivo 18528 2011-07-04 16:48 Mieken_exec_go_.6 -rwxr-xr-x 1 ivo ivo 913920 2011-06-03 16:13 panic.exe -rw-r--r-- 1 ivo ivo 180 2011-04-11 20:39 panic.go // 2nd example: show all processes pid, err = os.StartProcess("/bin/ps", []string{"-e", "-opid,ppid,comm"}, procAttr) if err != nil {fmt.Printf("Error %v starting process!", err) //os.Exit(1) }fmt.Printf("The process id is %v", pid) // 2) exec.Run // /***************/ // Linux: OK, but not for ls ? // cmd := exec.Command("ls", "-l") // no error, but doesn't show anything ? // cmd := exec.Command("ls") // no error, but doesn't show anything ?cmd := exec.Command("gedit") // this opens a gedit-windowerr = cmd.Run()if err != nil {fmt.Printf("Error %v executing command!", err)os.Exit(1)}fmt.Printf("The command is %v", cmd) // The command is &{/bin/ls [ls -l] [] <nil> <nil> <nil> 0xf840000210 <nil> true [0xf84000ea50 0xf84000e9f0 0xf84000e9c0] [0xf84000ea50 0xf84000e9f0 0xf84000e9c0] [] [] 0xf8400128c0} } // in Windows: uitvoering: Error fork/exec /bin/ls: The system cannot find the path specified. starting process!

總結

以上是生活随笔為你收集整理的golang中的shell的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。