go exec 之cmd 四种实用用法

cmd字段介绍

type Cmd struct {  

    Path         string   //运行命令的路径,绝对路径或者相对路径  

    Args         []string   // 命令参数  

    Env          []string         //进程环境,如果环境为空,则使用当前进程的环境  

    Dir          string   //指定command的工作目录,如果dir为空,则comman在调用进程所在当前目录中运行  

    Stdin        io.Reader  //标准输入,如果stdin是nil的话,进程从null device中读取(os.DevNull),stdin也可以时一个文件,否则的话则在运行过程中再开一个goroutine去  

             //读取标准输入  

    Stdout       io.Writer       //标准输出  

    Stderr       io.Writer  //错误输出,如果这两个(Stdout和Stderr)为空的话,则command运行时将响应的文件描述符连接到os.DevNull  

    ExtraFiles   []*os.File     

    SysProcAttr  *syscall.SysProcAttr  

    Process      *os.Process    //Process是底层进程,只启动一次  

    ProcessState *os.ProcessState  //ProcessState包含一个退出进程的信息,当进程调用Wait或者Run时便会产生该信息.  

}  

 

用法一:直接在当前目录使用并返回结果

func Cmd(commandName string, params []string) (string, error) {
    cmd := exec.Command(commandName, params...)
    fmt.Println("Cmd", cmd.Args)
    var out bytes.Buffer
    cmd.Stdout = &out
    cmd.Stderr = os.Stderr
    err := cmd.Start()
    if err != nil {
        return "", err
    }
    err = cmd.Wait()
    return out.String(), err
}

用法二:在命令位置使用并返回结果

func CmdAndChangeDir(dir string, commandName string, params []string) (string, error) {
    cmd := exec.Command(commandName, params...)
    fmt.Println("CmdAndChangeDir", dir, cmd.Args)
    var out bytes.Buffer
    cmd.Stdout = &out
    cmd.Stderr = os.Stderr
    cmd.Dir = dir
    err := cmd.Start()
    if err != nil {
        return "", err
    }
    err = cmd.Wait()
    return out.String(), err
}

用法三:在命令位置使用并实时输出每行结果

func CmdAndChangeDirToShow(dir string, commandName string, params []string) error {
  cmd := exec.Command(commandName, params...)
  fmt.Println("CmdAndChangeDirToFile", dir, cmd.Args)
  //StdoutPipe方法返回一个在命令Start后与命令标准输出关联的管道。Wait方法获知命令结束后会关闭这个管道,一般不需要显式的关闭该管道。
  stdout, err := cmd.StdoutPipe()
  if err != nil {
    fmt.Println("cmd.StdoutPipe: ", err)
    return err
  }
  cmd.Stderr = os.Stderr
  cmd.Dir = dir
  err = cmd.Start()
  if err != nil {
    return err
  }
  //创建一个流来读取管道内内容,这里逻辑是通过一行一行的读取的
  reader := bufio.NewReader(stdout)
  //实时循环读取输出流中的一行内容
  for {
    line, err2 := reader.ReadString('\n')
    if err2 != nil || io.EOF == err2 {
      break
    }
    fmt.Println(line)
  }
  err = cmd.Wait()
  return err
}

用法四:在命令位置使用并实时写入每行结果到文件

func CmdAndChangeDirToFile(fileName, dir, commandName string, params []string) error {
    Path, err := GetCurrentPath()
    if err != nil {
        return err
    }
    Path += "logs/cmdDir/"
    EnsureDir(Path)
    f, err := os.Create(Path + fileName) //创建文件
    defer f.Close()
    cmd := exec.Command(commandName, params...)
    fmt.Println("CmdAndChangeDirToFile", dir, cmd.Args)
    //StdoutPipe方法返回一个在命令Start后与命令标准输出关联的管道。Wait方法获知命令结束后会关闭这个管道,一般不需要显式的关闭该管道。
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Println("cmd.StdoutPipe: ", err)
        return err
    }
    cmd.Stderr = os.Stderr
    cmd.Dir = dir
    err = cmd.Start()
    if err != nil {
        return err
    }
    //创建一个流来读取管道内内容,这里逻辑是通过一行一行的读取的
    reader := bufio.NewReader(stdout)
    //实时循环读取输出流中的一行内容
    for {
        line, err2 := reader.ReadString('\n')
        if err2 != nil || io.EOF == err2 {
            break
        }
        _, err = f.WriteString(line) //写入文件(字节数组)
        f.Sync()
    }
    _, err = f.WriteString("=================处理完毕========================") //写入文件(字节数组)
    f.Sync()
    err = cmd.Wait()
    return err
}

 

 

你可能感兴趣的:(go日常收集)