Go exec 命令
最后修改时间 2024 年 4 月 11 日
在本文中,我们将展示如何在 Golang 中执行 shell 命令和程序。
Run
函数启动指定的命令并等待其完成,而 Start
启动指定的命令但不等待其完成;我们需要将 Wait
与 Start
一起使用。
Go os/exec
os/exec
包运行外部命令。它封装了 os.StartProcess
,以便更轻松地重新映射 stdin 和 stdout,使用管道连接 I/O,以及进行其他调整。
Go exec 程序
Run
启动指定的命令并等待其完成。
package main import ( "log" "os/exec" ) func main() { cmd := exec.Command("firefox") err := cmd.Run() if err != nil { log.Fatal(err) } }
在代码示例中,我们执行 Firefox 浏览器。
Go exec.Command
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"
Go exec 命令带多个参数
我们可以向 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
Go exec 命令捕获输出
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
命令的输出并打印它。
Go 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 中,我们将一个字符串写入 stdin 管道。
$ go run stdinpipe.go an old falcon
Go 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
等待命令退出,并等待 stdin 的所有复制或 stdout 或 stderr 的复制完成。它会在看到命令退出后关闭管道。
$ go run stdoutpipe.go AN OLD FALCON
来源
在本文中,我们执行了 Golang 中的外部命令。