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 中的外部命令。