exec包可以用于执行外部命令。简单来说,就是可以用该包来执行其它的应用程序(比如shell脚本,或者其它任意可执行程序)。它对os.StartProcess函数做了包装,以便更容易的对输入输出做处理,使用管道连接I/O,以及作其它的一些调整 。
包:os/exec
- 下面先看这个包的基本方法
func Command(name string, arg ...string) *Cmd // 这个方法返回一个可执行程序的对象(我们就把结构体看成对象),需要的参数:name是要执行的命令;arg是传给命令的参数,是可选的; 注意:name参数,如果传入的值有路径分隔符那就是一个在磁盘中实时存在的可执行程序(比如/usr/local/bin/go,这是go的启动程序),如果没有分隔符,那么会去环境变量PATH中查找类似的程序(比如传入go,那就会去环境变量中找是否有类似go的可执行程序),没理解不关系,我们下面等会儿看例子就明白了。
func (c *Cmd) Output() ([]byte, error) // 执行命令并返回程序的标准输出(就是返回程序输出的内容,这里返回的是切片)
func (c *Cmd) CombinedOutput() ([]byte, error) // 执行命令并返回标准输出和错误输出合并的切片,做了解,用得不多
- 通过一个简单的例子了解一下,我们用go来执行一个shell脚本:
1.我们新建一个a.sh脚本,并赋予可执行权限(linux下),
2
2.脚本内容(输出一行hello world和第一个参数):
#!/usr/bin/env bash
echo hello world $1
3.看代码:
package main
import (
"log"
"os"
"os/exec"
)
func main() {
wd, _ := os.Getwd() // 获取当前工作目录
cmd := exec.Command(wd+"/src/a.sh", "dalgurak") // 组建可执行程序,给程序传入的参数为一个字符串dalgurak
b, _ := cmd.Output() // 执行命令程序,并返回程序的输出的切片和错误
log.Println(string(b)) // 打印
}
4.运行结果如下:
可以看到,正确的执行了src目录下的a.sh脚本,并打印了传入的dalgurak参数。
- 下面再介绍exec包的其它方法:
func (c *Cmd) Run() error // 开始执行c包含的执行命令,并阻塞直到命令执行完毕,由于是阻塞的,所以它是同步方法和Output方法类似,只是前者很方便就能拿到程序的输出内容。Run不方便拿到程序执行输出的内容
func (c *Cmd) Start() error // 开始执行c包含的命令,但并不会等待该命令完成,它会立即返回。Wait方法会返回命令的返回状态码并在命令返回后释放相关的资源。所以可以把它看做是异步的执行方法
func (c *Cmd) Wait() error // Wait会阻塞直到该命令执行完成,这个命令必须和start命令配合使用,由上面可以看出,start开始执行,但不但表执行完成,wait等待命令执行完成。
下面看例子(用Start方法异步执行程序,Run和Output方法类似都是同步执行,一行代码就搞定,所以不在浪费篇幅演示):
package main
import (
"log"
"os"
"os/exec"
)
func main() {
wd, _ := os.Getwd() // 获取当前工作目录
cmd := exec.Command(wd+"/src/a.sh", "dalgurak") // 组建可执行程序,给程序传入的参数为一个字符串dalgurak
b := make([]byte, 1024)
r, _ := cmd.StdoutPipe() // 获取程序的标准输出
cmd.Start() // 启动程序
n, _ := r.Read(b) // 读取程序标准输出的内容
log.Println(string(b[:n])) // 打印
}
运行结果:
上面看到,也正确打印了结果,上面有一个StdoutPipe方法,这个方法用于获取cmd程序执行过程中,输出的内容,说白了就是日志,我们通过这个方法可以拿到;不仅如此,我们还可以拿到cmd程序的标准输入和标准错误:
func (c *Cmd) StdinPipe() (io.WriteCloser, error) // StdinPipe方法返回一个在命令Start后与命令标准输入关联的管道
func (c *Cmd) StderrPipe() (io.ReadCloser, error) //StderrPipe方法返回一个在命令Start后与命令标准错误输出关联的管道。
func (c *Cmd) StdoutPipe() (io.ReadCloser, error) // StdoutPipe方法返回一个在命令Start后与命令标准输出关联的管道
其实这些StdinPipe等我们用的都不多,着重了解一下怎么用go去调用运行其它第三方程序就行了,用
Command方法获取一个命令执行对象,再用Run或者Output方法同步阻塞执行,或者用Start异步执行。