Cmd 代表正在准备或运行的外部命令。
调用它的 Run,Output 或 CombinedOutput 方法后,Cmd 不能重用。

  1. type Cmd struct {
  2. // Path is the path of the command to run.
  3. //
  4. // This is the only field that must be set to a non-zero
  5. // value. If Path is relative, it is evaluated relative
  6. // to Dir.
  7. Path string
  8. // Args holds command line arguments, including the command as Args[0].
  9. // If the Args field is empty or nil, Run uses {Path}.
  10. //
  11. // In typical use, both Path and Args are set by calling Command.
  12. Args []string
  13. // Env specifies the environment of the process.
  14. // Each entry is of the form "key=value".
  15. // If Env is nil, the new process uses the current process's
  16. // environment.
  17. // If Env contains duplicate environment keys, only the last
  18. // value in the slice for each duplicate key is used.
  19. Env []string
  20. // Dir specifies the working directory of the command.
  21. // If Dir is the empty string, Run runs the command in the
  22. // calling process's current directory.
  23. Dir string
  24. // Stdin specifies the process's standard input.
  25. // If Stdin is nil, the process reads from the null device (os.DevNull).
  26. // If Stdin is an *os.File, the process's standard input is connected
  27. // directly to that file.
  28. // Otherwise, during the execution of the command a separate
  29. // goroutine reads from Stdin and delivers that data to the command
  30. // over a pipe. In this case, Wait does not complete until the goroutine
  31. // stops copying, either because it has reached the end of Stdin
  32. // (EOF or a read error) or because writing to the pipe returned an error.
  33. Stdin io.Reader
  34. // Stdout and Stderr specify the process's standard output and error.
  35. //
  36. // If either is nil, Run connects the corresponding file descriptor
  37. // to the null device (os.DevNull).
  38. //
  39. // If Stdout and Stderr are the same writer, and have a type that can be compared with ==,
  40. // at most one goroutine at a time will call Write.
  41. Stdout io.Writer
  42. Stderr io.Writer
  43. // ExtraFiles specifies additional open files to be inherited by the
  44. // new process. It does not include standard input, standard output, or
  45. // standard error. If non-nil, entry i becomes file descriptor 3+i.
  46. ExtraFiles []*os.File
  47. // SysProcAttr holds optional, operating system-specific attributes.
  48. // Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
  49. SysProcAttr *syscall.SysProcAttr
  50. // Process is the underlying process, once started.
  51. Process *os.Process
  52. // ProcessState contains information about an exited process,
  53. // available after a call to Wait or Run.
  54. ProcessState *os.ProcessState
  55. // contains filtered or unexported fields
  56. }

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

命令返回 Cmd 结构来执行具有给定参数的命名程序。
它仅在返回的结构中设置 Path 和 Args 。
如果名称不包含路径分隔符,Command 将尽可能使用 LookPath 将名称解析为完整路径。否则,它直接使用名称作为路径。
返回的 Cmd 的 Args 字段由命令名称和后面的 arg 元素构成,所以 arg 不应包含命令名称本身。例如,Command(“echo”,“hello”)。Args0 始终是名称,而不是可能解析的路径。

  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "log"
  6. "os/exec"
  7. "strings"
  8. )
  9. func main() {
  10. cmd := exec.Command("tr", "a-z", "A-Z")
  11. cmd.Stdin = strings.NewReader("some input")
  12. var out bytes.Buffer
  13. cmd.Stdout = &out
  14. err := cmd.Run()
  15. if err != nil {
  16. log.Fatal(err)
  17. }
  18. fmt.Printf("in all caps: %q\n", out.String())

func (*Cmd) Run

运行开始指定的命令并等待它完成。
如果命令运行,则返回的错误为零,在复制 stdin,stdout 和 stderr 时没有问题,并以零退出状态退出。
如果该命令启动但未成功完成,则错误类型为 * ExitError 。其他错误类型可能会返回其他情况。

  1. package main
  2. import (
  3. "log"
  4. "os/exec"
  5. )
  6. func main() {
  7. cmd := exec.Command("sleep", "1")
  8. log.Printf("Running command and waiting for it to finish...")
  9. err := cmd.Run()
  10. log.Printf("Command finished with error: %v", err)
  11. }

func (*Cmd) Start

开始启动指定的命令,但不等待它完成。
一旦命令退出,Wait 方法将返回退出代码并释放相关资源。

  1. package main
  2. import (
  3. "log"
  4. "os/exec"
  5. )
  6. func main() {
  7. cmd := exec.Command("sleep", "5")
  8. err := cmd.Start()
  9. if err != nil {
  10. log.Fatal(err)
  11. }
  12. log.Printf("Waiting for command to finish...")
  13. err = cmd.Wait()
  14. log.Printf("Command finished with error: %v", err)
  15. }

func (*Cmd) Wait

等待等待命令退出并等待任何复制到标准输入或从标准输出或标准错误复制完成。
该命令必须由 Start 启动。
如果命令运行,则返回的错误为零,在复制 stdin,stdout 和 stderr 时没有问题,并以零退出状态退出。
如果该命令无法运行或未成功完成,则错误类型为 ExitError 。其他错误类型可能会返回 I/O 问题。
如果 c.Stdin 不是
os.File,则 Wait 还会等待从 c.Stdin 复制到流程的标准输入的 I/O 循环完成。
等待释放与 Cmd 相关的任何资源。

如何实时获取shell命令的打印结果

  1. cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("./mysql/bin/mysqlsh -h%s -u%s -p%s -D%s --sql <<EOF\n source %s\nEOF", mysqlConfig.Host, mysqlConfig.User, mysqlConfig.Password, mysqlConfig.DBName, fileName))
  2. stdout, _ := cmd.StdoutPipe()
  3. strderr, _ := cmd.StderrPipe()
  4. if err := cmd.Start(); err != nil {
  5. panic("err")
  6. }
  7. go asyncLog(stdout)
  8. go asyncLog(strderr)
  9. if err := cmd.Wait(); err != nil {
  10. panic(err)
  11. }
  12. func asyncLog(reader io.ReadCloser) error {
  13. cache := "" //缓存不足一行的日志信息
  14. buf := make([]byte, 1024)
  15. for {
  16. num, err := reader.Read(buf)
  17. if err != nil && err != io.EOF {
  18. return err
  19. }
  20. if num > 0 {
  21. b := buf[:num]
  22. s := strings.Split(string(b), "\n")
  23. line := strings.Join(s[:len(s)-1], "\n") //取出整行的日志
  24. fmt.Printf("%s%s\n", cache, line)
  25. cache = s[len(s)-1]
  26. }
  27. }
  28. return nil
  29. }