exec是os包中的一个子包,可用于使用Go运行外部命令。Goexec命令教程展示了如何在Golang中执行shell命令和程序。要使用这个包,我们需要按如下方式导入:import"os/exec"1.使用GoLangexec包运行命令我们可以运行任何我们想要的命令。它可以像我们使用CMD、bash或其他一些shell运行命令一样运行命令。这是运行ls命令的示例。创建一个新的main.go:packagemainimport("fmt""os/exec")funcmain(){cmd:=exec.Command("ls")e:=cmd.Run()CheckError(e)}funcCheckError(eerror){ife!=nil{fmt.Println(e)}}Run函数启动指定命令并等待它完成,而Start启动指定命令但不等待它完成;我们需要使用WaitwithStart。然后创建一个新的go.mod文件:$gomodinitmain.gogo:creatingnewgo.mod:modulemain.gogo:toaddmodulerequirementsandsums:gomodtidy现在,程序会运行,但我们不会查看控制站的任何输出。原因是命令运行并且输出未发送到标准输出。$gorunmain.go所以,我们需要解决这个问题。添加如下所示的两行以查看控制台的任何输出。cmd.Stdout=os.Stdoutcmd.Stderr=os.Stderr输出将显示当前目录中的文件。packagemainimport("fmt""os""os/exec")funcmain(){cmd:=exec.Command("ls","-lah")cmd.Stdout=os.Stdoutcmd.Stderr=os.Stderre:=cmd.Run()CheckError(e)}funcCheckError(eerror){ife!=nil{fmt.Println(e)}}然后我们重新编程,可以看到标准平台输出了如下文件:$gorunmain.gototal16drwxr-xr-x4yuzhou_1su员工128B51522:56.drwxr-xr-x23yuzhou_1su员工736B51522:53..-rw-r--r--1yuzhou_1su员工24B51522:56go.mod-rw-r--r--1yuzhou_1sustaff248B51523:18main.go直接用ls运行这个命令,可以看到结果是正确的:$ls-alhtotal16drwxr-xr-x4yuzhou_1su员工128B51522:56.drwxr-xr-x23yuzhou_1su员工736B51522:53..-rw-r--r--1yuzhou_1su员工24B51522:56去.mod-rw-r--r--1yuzhou_1sustaff248B51523:18main.go2.为不同的操作系统指定命令我们可以指定为不同的操作系统运行不同的命令(比如Linux上的bash命令)。这是一个例子。ifruntime.GOOS=="linux"{cmd=exec.Command("ls")}为此我们还需要导入运行时包。要查看所有可能的操作系统,我们可以运行gotooldistlist,它将显示所有可能的操作系统和ARCH组合。3.Goexec命令捕获输出运行命令并返回其标准输出:packagemainimport("fmt""log""os/exec")funcmain(){out,err:=exec.Command("ls","-l").Output()iferr!=nil{log.Fatal(err)}fmt.Println(string(out))}运行程序:$gorunmain.gototal16-rw-r--r--1yuzhou_1sustaff2451522:56go.mod-rw-r--r--1yuzhou_1sustaff18051523:33main.go4.Gocmd.StdinPipe允许我们发送一个命令的输出给另一个订单。StdinPipe返回一个管道,该管道将在命令启动时连接到命令的标准输入。packagemainimport("fmt""io""log""os/exec")funcmain(){cmd:=exec.Command("cat")stdin,err:=cmd.StdinPipe()iferr!=nil{log.Fatal(err)}gofunc(){deferstdin.Close()io.WriteString(stdin,"anoldfalcon")}()out,err:=cmd.CombinedOutput()iferr!=nil{日志.Fatal(err)}fmt.Printf("%s\n",out)}在代码示例中,我们将字符串写入goroutine内的标准输入。cmd:=exec.Command("cat")cat命令将给定的文件连接到标准输出。当没有给出文件或带有-时,该命令读取标准输入并将其打印到标准输出。stdin,err:=cmd.StdinPipe()我们得到了cat命令的标准输入管道。gofunc(){deferstdin.Close()io.WriteString(stdin,"anoldfalcon")}()在goroutine中,我们将一个字符串写入stdin管道。$gorunstdinpipe.goanoldfalcon5.Gocmd.StdoutPipeStdoutPipe返回一个管道,该管道将在命令启动时连接到命令的标准输出。packagemainimport("fmt""io/ioutil""log""os/exec""strings")funcupper(datastring)string{returnstrings.ToUpper(data)}funcmain(){cmd:=exec.Command("echo","anoldfalcon")stdout,err:=cmd.StdoutPipe()iferr!=nil{log.Fatal(err)}如果err:=cmd.Start();err!=nil{log.Fatal(err)}数据,err:=ioutil.ReadAll(stdout)iferr!=nil{log.Fatal(err)}iferr:=cmd.Wait();err!=nil{log.Fatal(err)}fmt.Printf("%s\n",upper(string(data)))}此示例通过管道传输echo命令的输出并将其转换为大写。cmd:=exec.Command("echo","anoldfalcon")要运行的命令是带有单个字符串参数的echo命令。stdout,err:=cmd.StdoutPipe()我们得到了标准输出管道。如果错误:=cmd.Start();err!=nil{log.Fatal(err)}使用Start函数执行命令;它不会等待它完成。data,err:=ioutil.ReadAll(stdout)我们从管道中读取数据。如果错误:=cmd.Wait();err!=nil{log.Fatal(err)}Wait等待命令退出并等待任何复制到stdin或从stdout或stderr完成。它在看到命令退出后关闭管道。运行程序:$gorunstdoutpipe.goANOLDFALCON6.总结os/exec包以运行外部命令。它包装了os.StartProcess以更轻松地重新映射标准输入和标准输出、使用管道连接I/O以及进行其他调整。参考链接:https://zetcode.com/golang/exec-command/
