os/exec 执行命令、管道
在windows执行命令
cmd0 := exec.Command("cmd.exe","/C", "dir")
前两个参数是固定的,后面+命令
在linux中
cmd0 := exec.Command("ps","aux")
也可以加入一些参数
cmd0 := exec.Command("echo","-n", "你好")
使用Command 方法可以返回一个 cmd结构体
type Cmd struct {
// Path是将要执行的命令的路径。
//
// 该字段不能为空,如为相对路径会相对于Dir字段。
Path string
// Args保管命令的参数,包括命令名作为第一个参数;如果为空切片或者nil,相当于无参数命令。
//
// 典型用法下,Path和Args都应被Command函数设定。
Args []string
// Env指定进程的环境,如为nil,则是在当前进程的环境下执行。
Env []string
// Dir指定命令的工作目录。如为空字符串,会在调用者的进程当前目录下执行。
Dir string
// Stdin指定进程的标准输入,如为nil,进程会从空设备读取(os.DevNull)
Stdin io.Reader
// Stdout和Stderr指定进程的标准输出和标准错误输出。
//
// 如果任一个为nil,Run方法会将对应的文件描述符关联到空设备(os.DevNull)
//
// 如果两个字段相同,同一时间最多有一个线程可以写入。
Stdout io.Writer
Stderr io.Writer
// ExtraFiles指定额外被新进程继承的已打开文件流,不包括标准输入、标准输出、标准错误输出。
// 如果本字段非nil,entry i会变成文件描述符3+i。
//
// BUG: 在OS X 10.6系统中,子进程可能会继承不期望的文件描述符。
// http://golang.org/issue/2603
ExtraFiles []*os.File
// SysProcAttr保管可选的、各操作系统特定的sys执行属性。
// Run方法会将它作为os.ProcAttr的Sys字段传递给os.StartProcess函数。
SysProcAttr *syscall.SysProcAttr
// Process是底层的,只执行一次的进程。
Process *os.Process
// ProcessState包含一个已经存在的进程的信息,只有在调用Wait或Run后才可用。
ProcessState *os.ProcessState
// 内含隐藏或非导出字段
}
可以通过这个结构体的 方法获取 标准输出 、标准输出、标准错误输出的管道
ioWriterCloser ,err := cmd0.StdinPipe() ioReaderCloser,err := cmd0.StderrPipe() ioReaderCloser,err := cmd0.StdoutPipe()
管道方法返回 两种接口。
我们可以利用接口获取数据、写入其他命令
获取数据
cmd0 := exec.Command("cmd.exe","/C", "dir")
ioR ,err := cmd0.StderrPipe()
if err != nil {
panic("err")
}
r := bufio.NewReader(ioR)
l ,_,err := r.ReadLine()
if err != nil {
panic("err")
}
也可以通过 返回ioReader 接口 直接读数据,读到结尾判断EOF就可以了。
将一个命令的输出作为另外一个命令的输入 相当于 #ps aux | grep apipe
cmd1 := exec.Command("ps","aux")
cmd2 := exec.Command("grep","apipe")
var outPutBuf1 bytes.Buffer
//指定命令的标准输出
cmd1.Stdout = &outPutBuf1
//指定cmd2的标准输入
cmd2.Stdin = &outPutBuf1
管道还有os.Pipe() 、io.Pipe() 后者是基于内存的有原子性保障的单独管道
还有就是一个很关键的字段 cmd.ExtraFiles
可以像要打开的新进程中添加文件流
cmd.ExtraFiles = []*os.File{f}
文件流使用os.NewFile(3,"") 打开 ,因为前几个文件描述符 0、1、2 默认为 标准输入、标准输出、标准错误输出
浙公网安备 33010602011771号