os/exec

Package exec

  • import "os/exec"

  • Overview

  • Index

  • Examples

概观

包 exec 执行外部命令。它包装了 os.StartProcess ,以便重新映射 stdin 和 stdout ,使用管道连接 I/O 并进行其他调整。

与来自 C 和其他语言的“系统”库调用不同,os/exec 包有意不调用系统shell,并且不会扩展任何 glob 模式或处理通常由 shell 执行的其他扩展,管道或重定向。该软件包的行为更像 C 的 “exec” 系列功能。要扩展 glob 模式,请直接调用外壳,注意避开任何危险输入,或者使用 path/filepath 包的 Glob 函数。要扩展环境变量,请使用 package os 的 ExpandEnv 。

请注意,此包中的示例假定为Unix系统。它们可能无法在Windows上运行,并且它们不会在golang.org和godoc.org使用的Go Playground中运行。

Index

  • Variables

  • func LookPath(file string) (string, error)

  • type Cmd

  • func Command(name string, arg ...string) *Cmd

  • func CommandContext(ctx context.Context, name string, arg ...string) *Cmd

  • func (c *Cmd) CombinedOutput() ([]byte, error)

  • func (c *Cmd) Output() ([]byte, error)

  • func (c *Cmd) Run() error

  • func (c *Cmd) Start() error

  • func (c *Cmd) StderrPipe() (io.ReadCloser, error)

  • func (c *Cmd) StdinPipe() (io.WriteCloser, error)

  • func (c *Cmd) StdoutPipe() (io.ReadCloser, error)

  • func (c *Cmd) Wait() error

  • type Error

  • func (e *Error) Error() string

  • type ExitError

  • func (e *ExitError) Error() string

例子

Cmd.CombinedOutput Cmd.Output Cmd.Run Cmd.Start Cmd.StderrPipe Cmd.StdinPipe Cmd.StdoutPipe Command CommandContext Command (Environment) LookPath

包文件

exec.go exec_unix.go lp_unix.go

变量

ErrNotFound 是如果路径搜索未能找到可执行文件导致的错误。

var ErrNotFound = errors.New("executable file not found in $PATH")

func LookPath(显示源文件)

func LookPath(file string) (string, error)

LookPath 在由 PATH 环境变量命名的目录中搜索名为 file 的可执行二进制文件。如果文件包含斜线,则直接尝试并且不会咨询 PATH 。结果可能是相对于当前目录的绝对路径或路径。

package main import ( "fmt" "log" "os/exec" ) func main() { path, err := exec.LookPath("fortune") if err != nil { log.Fatal("installing fortune is in your future") } fmt.Printf("fortune is available at %s\n", path) }

type Cmd(显示源文件)

Cmd 代表正在准备或运行的外部命令。

调用它的 Run,Output 或 CombinedOutput 方法后,Cmd 不能重用。

type Cmd struct { // Path is the path of the command to run. // // This is the only field that must be set to a non-zero // value. If Path is relative, it is evaluated relative // to Dir. Path string // Args holds command line arguments, including the command as Args[0]. // If the Args field is empty or nil, Run uses {Path}. // // In typical use, both Path and Args are set by calling Command. Args []string // Env specifies the environment of the process. // Each entry is of the form "key=value". // If Env is nil, the new process uses the current process's // environment. // If Env contains duplicate environment keys, only the last // value in the slice for each duplicate key is used. Env []string // Dir specifies the working directory of the command. // If Dir is the empty string, Run runs the command in the // calling process's current directory. Dir string // Stdin specifies the process's standard input. // If Stdin is nil, the process reads from the null device (os.DevNull). // If Stdin is an *os.File, the process's standard input is connected // directly to that file. // Otherwise, during the execution of the command a separate // goroutine reads from Stdin and delivers that data to the command // over a pipe. In this case, Wait does not complete until the goroutine // stops copying, either because it has reached the end of Stdin // (EOF or a read error) or because writing to the pipe returned an error. Stdin io.Reader // Stdout and Stderr specify the process's standard output and error. // // If either is nil, Run connects the corresponding file descriptor // to the null device (os.DevNull). // // If Stdout and Stderr are the same writer, and have a type that can be compared with ==, // at most one goroutine at a time will call Write. Stdout io.Writer Stderr io.Writer // ExtraFiles specifies additional open files to be inherited by the // new process. It does not include standard input, standard output, or // standard error. If non-nil, entry i becomes file descriptor 3+i. ExtraFiles []*os.File // SysProcAttr holds optional, operating system-specific attributes. // Run passes it to os.StartProcess as the os.ProcAttr's Sys field. SysProcAttr *syscall.SysProcAttr // Process is the underlying process, once started. Process *os.Process // ProcessState contains information about an exited process, // available after a call to Wait or Run. ProcessState *os.ProcessState // contains filtered or unexported fields }

func Command(显示源文件)

func Command(name string, arg ...string) *Cmd

命令返回 Cmd 结构来执行具有给定参数的命名程序。

它仅在返回的结构中设置 Path 和 Args 。

如果名称不包含路径分隔符,Command 将尽可能使用 LookPath 将名称解析为完整路径。否则,它直接使用名称作为路径。

返回的 Cmd 的 Args 字段由命令名称和后面的 arg 元素构成,所以 arg 不应包含命令名称本身。例如,Command(“echo”,“hello”)。Args0 始终是名称,而不是可能解析的路径。

package main import ( "bytes" "fmt" "log" "os/exec" "strings" ) func main() { cmd := exec.Command("tr", "a-z", "A-Z") cmd.Stdin = strings.NewReader("some input") var out bytes.Buffer cmd.Stdout = &out err := cmd.Run() if err != nil { log.Fatal(err) } fmt.Printf("in all caps: %q\n", out.String()) }

示例(环境)

package main import ( "log" "os" "os/exec" ) func main() { cmd := exec.Command("prog") cmd.Env = append(os.Environ(), "FOO=duplicate_value", // ignored "FOO=actual_value", // this value is used ) if err := cmd.Run( err != nil { log.Fatal(err) } }

func CommandContext(显示源文件)

func CommandContext(ctx context.Context, name string, arg ...string) *Cmd

CommandContext 与 Command 相似,但包含一个上下文。

如果上下文在命令完成之前完成,则提供的上下文用于终止进程(通过调用 os.Process.Kill )。

package main import ( "context" "os/exec" "time" ) func main() { ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) defer cancel() if err := exec.CommandContext(ctx, "sleep", "5").Run( err != nil { // This will fail after 100 milliseconds. The 5 second sleep // will be interrupted. } }

func (*Cmd) CombinedOutput(显示源文件)

func (c *Cmd) CombinedOutput() ([]byte, error)

CombinedOutput 运行该命令并返回其组合标准输出和标准错误。

package main import ( "fmt" "log" "os/exec" ) func main() { cmd := exec.Command("sh", "-c", "echo stdout; echo 1>&2 stderr") stdoutStderr, err := cmd.CombinedOutput() if err != nil { log.Fatal(err) } fmt.Printf("%s\n", stdoutStderr) }

func (*Cmd) Output(显示源文件)

func (c *Cmd) Output() ([]byte, error)

输出运行该命令并返回其标准输出。任何返回的错误通常都是 * ExitError 类型。如果 c.Stderr 为零,则输出填充 ExitError.Stderr 。

package main import ( "fmt" "log" "os/exec" ) func main() { out, err := exec.Command("date").Output() if err != nil { log.Fatal(err) } fmt.Printf("The date is %s\n", out) }

func (*Cmd) Run(显示源文件)

func (c *Cmd) Run() error

运行开始指定的命令并等待它完成。

如果命令运行,则返回的错误为零,在复制 stdin,stdout 和 stderr 时没有问题,并以零退出状态退出。

如果该命令启动但未成功完成,则错误类型为 * ExitError 。其他错误类型可能会返回其他情况。

package main import ( "log" "os/exec" ) func main() { cmd := exec.Command("sleep", "1") log.Printf("Running command and waiting for it to finish...") err := cmd.Run() log.Printf("Command finished with error: %v", err) }

func (*Cmd) Start(显示源文件)

func (c *Cmd) Start() error

开始启动指定的命令,但不等待它完成。

一旦命令退出,Wait 方法将返回退出代码并释放相关资源。

package main import ( "log" "os/exec" ) func main() { cmd := exec.Command("sleep", "5") err := cmd.Start() if err != nil { log.Fatal(err) } log.Printf("Waiting for command to finish...") err = cmd.Wait() log.Printf("Command finished with error: %v", err) }

func (*Cmd) StderrPipe(显示源文件)

func (c *Cmd) StderrPipe() (io.ReadCloser, error)

当命令启动时,StderrPipe 将返回一个将连接到命令标准错误的管道。

等待会在看到命令退出后关闭管道,因此大多数呼叫者不需要关闭管道; 但是,含义是在从管道读取完成之前调用 Wait 是不正确的。出于同样的原因,在使用 StderrPipe 时使用 Run 是不正确的。查看 StdoutPipe 示例了解惯用用法。

package main import ( "fmt" "io/ioutil" "log" "os/exec" ) func main() { cmd := exec.Command("sh", "-c", "echo stdout; echo 1>&2 stderr") stderr, err := cmd.StderrPipe() if err != nil { log.Fatal(err) } if err := cmd.Start( err != nil { log.Fatal(err) } slurp, _ := ioutil.ReadAll(stderr) fmt.Printf("%s\n", slurp) if err := cmd.Wait( err != nil { log.Fatal(err) } }

func (*Cmd) StdinPipe(显示源文件)

func (c *Cmd) StdinPipe() (io.WriteCloser, error)

当命令启动时,StdinPipe 返回一个将连接到命令标准输入的管道。在 Wait 看到命令退出后,管道将自动关闭。呼叫者只需调用 Close 即可更快地关闭管道。例如,如果正在运行的命令在标准输入关闭之前不会退出,则调用者必须关闭管道。

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, "values written to stdin are passed to cmd's standard input") }() out, err := cmd.CombinedOutput() if err != nil { log.Fatal(err) } fmt.Printf("%s\n", out) }

func (*Cmd) StdoutPipe(显示源文件)

func (c *Cmd) StdoutPipe() (io.ReadCloser, error)

当命令启动时,StdoutPipe 返回一个将连接到命令标准输出的管道。

等待会在看到命令退出后关闭管道,因此大多数呼叫者不需要关闭管道; 但是,含义是在从管道读取完成之前调用 Wait 是不正确的。出于同样的原因,使用 StdoutPipe 时调用 Run 是不正确的。查看习惯用法的例子。

package main import ( "encoding/json" "fmt" "log" "os/exec" ) func main() { cmd := exec.Command("echo", "-n", `{"Name": "Bob", "Age": 32}`) stdout, err := cmd.StdoutPipe() if err != nil { log.Fatal(err) } if err := cmd.Start( err != nil { log.Fatal(err) } var person struct { Name string Age int } if err := json.NewDecoder(stdout).Decode(&person err != nil { log.Fatal(err) } if err := cmd.Wait( err != nil { log.Fatal(err) } fmt.Printf("%s is %d years old\n", person.Name, person.Age) }

func (*Cmd) Wait(显示源文件)

func (c *Cmd) Wait() error

等待等待命令退出并等待任何复制到标准输入或从标准输出或标准错误复制完成。

该命令必须由 Start 启动。

如果命令运行,则返回的错误为零,在复制 stdin,stdout 和 stderr 时没有问题,并以零退出状态退出。

如果该命令无法运行或未成功完成,则错误类型为 * ExitError 。其他错误类型可能会返回 I/O 问题。

如果 c.Stdin 不是 * os.File,则 Wait 还会等待从 c.Stdin 复制到流程的标准输入的 I/O 循环完成。

等待释放与 Cmd 相关的任何资源。

type Error(显示源文件)

错误记录了未能执行的二进制文件的名称及其失败的原因。

type Error struct { Name string Err error }

func (*Error) Error(显示源文件)

func (e *Error) Error() string

type ExitError(显示源文件)

ExitError 通过命令报告不成功的退出。

type ExitError struct { *os.ProcessState // Stderr holds a subset of the standard error output from the // Cmd.Output method if standard error was not otherwise being // collected. // // If the error output is long, Stderr may contain only a prefix // and suffix of the output, with the middle replaced with // text about the number of omitted bytes. // // Stderr is provided for debugging, for inclusion in error messages. // Users with other needs should redirect Cmd.Stderr as needed. Stderr []byte }

func (*ExitError) Error(显示源文件)

func (e *ExitError) Error() string