有时候我们的go程序需要执行外部的命令,比如执行linux shell命令,一个其他语言(比如C语言)编写的二进制文件,我们都可以通过调用go语言exec包的函数来执行。下面将介绍exec包的一些简单使用例子。
1. exec.Command执行命令
假设我们要执行调用linux的ping命令,求的5次ping的平均值,可以采用如下方式:
package main
import (
"bufio"
"fmt"
"io"
"os/exec"
"strings"
)
func exec_shell(s_cmd string) (string, bool) {
cmd := exec.Command("/bin/bash", "-c", s_cmd)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Error("cmd StdoutPipe error:", err)
return "", false
}
cmd.Start()
var end_line string
reader := bufio.NewReader(stdout)
for {
line, err2 := reader.ReadString('\n')
if err2 != nil || io.EOF == err2 {
break
}
end_line = line
}
fmt.Println(cmd.Process.Pid)
return end_line, true
}
func ping() string {
s_cmd := "ping -c 10 127.0.0.1"
var pline string
var b bool
if pline, b = exec_shell(s_cmd); b == false {
return ""
}
arr := strings.Split(pline, " ")
var a []string
if len(arr)-2 >= 0 {
a = strings.Split(arr[len(arr)-2], "/")
}
if len(a) >= 2 {
return a[1]
}
return ""
}
func main() {
for i := 0; i < 10; i++ {
str := ping()
fmt.Println(str)
}
}
其中,各个exec函数的简要介绍如下
func Command(name string, arg ...string) *Cmd
//方法返回一个*Cmd, 用于执行name指定的程序(携带arg参数)
func (c *Cmd) Run() error
//执行Cmd中包含的命令,阻塞直到命令执行完成
func (c *Cmd) Start() error
//执行Cmd中包含的命令,该方法立即返回,并不等待命令执行完成
func (c *Cmd) Wait() error
//该方法会阻塞直到Cmd中的命令执行完成,但该命令必须是被Start方法开始执行的
func (c *Cmd) Output() ([]byte, error)
//执行Cmd中包含的命令,并返回标准输出的切片
func (c *Cmd) CombinedOutput() ([]byte, error)
//执行Cmd中包含的命令,并返回标准输出与标准错误合并后的切片
func (c *Cmd) StdinPipe() (io.WriteCloser, error)
//返回一个管道,该管道会在Cmd中的命令被启动后连接到其标准输入
func (c *Cmd) StdoutPipe() (io.ReadCloser, error)
//返回一个管道,该管道会在Cmd中的命令被启动后连接到其标准输出
func (c *Cmd) StderrPipe() (io.ReadCloser, error)
//返回一个管道,该管道会在Cmd中的命令被启动后连接到其标准错误
2. go检测目标进程是否存在
if err = syscall.Kill(pid,0);err == nil {
fmt.Println("进程存在")
return
}
3. 杀死进程的方式
cmd := exec.Command("/bin/sh", "-c", "...........")
// Go会将PGID设置成与PID相同的值
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
syscall.Kill(cmd.Process.Pid, syscall.SIGKILL)