Goexec命令教程展示了如何在Golang中执行shell命令和程序。
Run
函数启动指定的命令并等待它完成,而Start
函数启动指定的命令但不等待它完成;我们需要使用Wait
和Start
。
去操作系统/执行
os/exec
包运行外部命令。它包装了os.StartProcess
,以便更轻松地重新映射标准输入和标准输出、使用管道连接I/O以及进行其他调整。
$ go version go version go1.18.1 linux/amd64
我们使用Go版本1.18。
执行程序
Run
启动指定的命令并等待它完成。
package main import ( "log" "os/exec" ) func main() { cmd := exec.Command("firefox") err := cmd.Run() if err != nil { log.Fatal(err) } }
在代码示例中,我们执行Firefox浏览器。
执行命令
Command
返回Cmd结构以使用给定的参数执行指定的程序。第一个参数是要运行的程序;其他参数是程序的参数。
package main import ( "bytes" "fmt" "log" "os/exec" "strings" ) func main() { cmd := exec.Command("tr", "a-z", "A-Z") cmd.Stdin = strings.NewReader("and old falcon") var out bytes.Buffer cmd.Stdout = &out err := cmd.Run() if err != nil { log.Fatal(err) } fmt.Printf("translated phrase: %q\n", out.String()) }
在代码示例中,我们通过tr
命令转换输入。
cmd := exec.Command("tr", "a-z", "A-Z")
tr
标准Linux命令转换、压缩和/或删除标准输入中的字符,写入标准输出。在我们的例子中,我们将小写字母转换为大写字母。
cmd.Stdin = strings.NewReader("and old falcon")
通过Stdin
字段,我们将字符串作为输入传递给命令。
var out bytes.Buffer cmd.Stdout = &out
程序的输出将写入字节缓冲区。
$ go run command.go translated phrase: "AND OLD FALCON"
执行带多个参数的命令
我们可以将多个参数传递给exec.Command
。
package main import ( "fmt" "os/exec" ) func main() { prg := "echo" arg1 := "there" arg2 := "are three" arg3 := "falcons" cmd := exec.Command(prg, arg1, arg2, arg3) stdout, err := cmd.Output() if err != nil { fmt.Println(err.Error()) return } fmt.Print(string(stdout)) }
该示例使用三个参数运行echo
命令。
$ go run multiple_args.go there are three falcons
goexec命令捕获输出
Output
运行命令并返回其标准输出。
package main import ( "fmt" "log" "os/exec" ) func main() { out, err := exec.Command("ls", "-l").Output() if err != nil { log.Fatal(err) } fmt.Println(string(out)) }
该示例捕获ls
命令的输出并将其打印出来。
转到cmd.StdinPipe
管道允许我们将一个命令的输出发送到另一个。StdinPipe
返回一个管道,该管道将在命令启动时连接到命令的标准输入。
package main import ( "fmt" "io" "log" "os/exec" ) func main() { cmd := exec.Command("cat") stdin, err := cmd.StdinPipe() if err != nil { log.Fatal(err) } go func() { defer stdin.Close() io.WriteString(stdin, "an old falcon") }() out, err := cmd.CombinedOutput() if err != nil { log.Fatal(err) } fmt.Printf("%s\n", out) }
在代码示例中,我们将字符串写入goroutine中的标准输入。
cmd := exec.Command("cat")
cat
命令将给定的文件连接到标准输出。当没有给定文件或带有-时,该命令读取标准输入并将其打印到标准输出。
stdin, err := cmd.StdinPipe()
我们得到了cat
命令的标准输入管道。
go func() { defer stdin.Close() io.WriteString(stdin, "an old falcon") }()
在goroutine中,我们将一个字符串写入标准输入管道。
$ go run stdinpipe.go an old falcon
转到cmd.StdoutPipe
StdoutPipe
返回一个管道,该管道将在命令启动时连接到命令的标准输出。
package main import ( "fmt" "io/ioutil" "log" "os/exec" "strings" ) func upper(data string) string { return strings.ToUpper(data) } func main() { cmd := exec.Command("echo", "an old falcon") stdout, err := cmd.StdoutPipe() if err != nil { log.Fatal(err) } if err := cmd.Start(); err != nil { log.Fatal(err) } data, err := ioutil.ReadAll(stdout) if err != nil { log.Fatal(err) } if err := cmd.Wait(); err != nil { log.Fatal(err) } fmt.Printf("%s\n", upper(string(data))) }
该示例通过管道读取echo
命令的输出并将其转换为大写字母。
cmd := exec.Command("echo", "an old falcon")
要运行的命令是带有单个字符串参数的echo
命令。
stdout, err := cmd.StdoutPipe()
我们得到了标准输出管道。
if err := cmd.Start(); err != nil { log.Fatal(err) }
命令是用Start
函数执行的;它不会等待它完成。
data, err := ioutil.ReadAll(stdout)
我们从管道中读取数据。
if err := cmd.Wait(); err != nil { log.Fatal(err) }
Wait
等待命令退出并等待任何复制tostdin或从stdout或stderr复制完成。它在看到命令退出后关闭管道。
$ go run stdoutpipe.go AN OLD FALCON
在本教程中,我们在Golang中执行了外部命令。
列出所有Go教程。