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(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())
func (*Cmd) Run
运行开始指定的命令并等待它完成。
如果命令运行,则返回的错误为零,在复制 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
开始启动指定的命令,但不等待它完成。
一旦命令退出,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) Wait
等待等待命令退出并等待任何复制到标准输入或从标准输出或标准错误复制完成。
该命令必须由 Start 启动。
如果命令运行,则返回的错误为零,在复制 stdin,stdout 和 stderr 时没有问题,并以零退出状态退出。
如果该命令无法运行或未成功完成,则错误类型为 ExitError 。其他错误类型可能会返回 I/O 问题。
如果 c.Stdin 不是 os.File,则 Wait 还会等待从 c.Stdin 复制到流程的标准输入的 I/O 循环完成。
等待释放与 Cmd 相关的任何资源。
如何实时获取shell命令的打印结果
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))
stdout, _ := cmd.StdoutPipe()
strderr, _ := cmd.StderrPipe()
if err := cmd.Start(); err != nil {
panic("err")
}
go asyncLog(stdout)
go asyncLog(strderr)
if err := cmd.Wait(); err != nil {
panic(err)
}
func asyncLog(reader io.ReadCloser) error {
cache := "" //缓存不足一行的日志信息
buf := make([]byte, 1024)
for {
num, err := reader.Read(buf)
if err != nil && err != io.EOF {
return err
}
if num > 0 {
b := buf[:num]
s := strings.Split(string(b), "\n")
line := strings.Join(s[:len(s)-1], "\n") //取出整行的日志
fmt.Printf("%s%s\n", cache, line)
cache = s[len(s)-1]
}
}
return nil
}