Go语言调用外部程序时支持管道符


原文链接: Go语言调用外部程序时支持管道符

sh -c "sting" -c 参数是从字符串执行的意思

 func run4() {
  	cmd := exec.Command("/bin/sh", "-c", `ps -eaf|grep "nginx: master"|grep -v "grep"|awk '{print $2}'`)
  	cmd.Stdout = os.Stdout
  	cmd.Stderr = os.Stderr
  	cmd.Run()
  }

有一个需求是用go语言程序调用外部命令时,允许使用管道符,如 ls | wc -l
Go语言对外部命令的调用进行了一定的封装,下面来试一下:

package main

import (

"os"
"os/exec"

)

func main() {

run1()

}

func run1() {

cmd := exec.Command("ls", "|", "wc", "-l")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Start()
cmd.Run()
cmd.Wait()

}

这样执行时,控制台会打出错误:
ls: 无法访问|: 没有那个文件或目录
ls: 无法访问wc: 没有那个文件或目录

难道Go程序不能使用管道符命令吗?带这此问题,我查了大量的资料,终于发现应该这样写(run2):

package main

import (

"os"
"os/exec"

)

func main() {

// run1()
run2()

}

func run1() {

cmd := exec.Command("ls", "|", "wc", "-l")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Start()
cmd.Run()
cmd.Wait()

}

func run2() {

c1 := exec.Command("ls")
c2 := exec.Command("wc", "-l")
c2.Stdin, _ = c1.StdoutPipe()
c2.Stdout = os.Stdout
c2.Stderr = os.Stderr
c2.Start()
c1.Run()
c2.Wait()

}

哈哈,这样就没问题啦。

下面,我们来点高级的,如查询 nginx 主进行的PID号:
ps -eaf|grep "nginx: master"|grep -v "grep"|awk '{print $2}'(见 run3)

package main

import (

"os"
"os/exec"

)

func main() {

// run1()
// run2()
run3()

}

func run1() {

cmd := exec.Command("ls", "|", "wc", "-l")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Start()
cmd.Run()
cmd.Wait()

}

func run2() {

c1 := exec.Command("ls")
c2 := exec.Command("wc", "-l")
c2.Stdin, _ = c1.StdoutPipe()
c2.Stdout = os.Stdout
c2.Stderr = os.Stderr
c2.Start()
c1.Run()
c2.Wait()

}

func run3() {

c1 := exec.Command("ps", "-eaf")
c2 := exec.Command("grep", `"nginx: master"`)
c3 := exec.Command("grep", "-v", `"grep"`)
c4 := exec.Command("awk", `'{print $2}'`)
c2.Stdin, _ = c1.StdoutPipe()
c3.Stdin, _ = c2.StdoutPipe()
c4.Stdin, _ = c3.StdoutPipe()

c4.Stdout = os.Stdout
c4.Stderr = os.Stderr

c4.Start()
c3.Start()
c2.Start()
c1.Run()
c4.Wait()

}

靠,又不行了,提示:
awk: 1: unexpected character '''
awk: 1: unexpected character '''
它不能支持参数中有引号的内容!

怎么办,难道真的没辙了吗?老天不负有心人,终于被我找到解决办法了,而且更简单:

package main

import (

"os"
"os/exec"

)

func main() {

// run1()
// run2()
// run3()
run4()

}

func run1() {

cmd := exec.Command("ls", "|", "wc", "-l")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Start()
cmd.Run()
cmd.Wait()

}

func run2() {

c1 := exec.Command("ls")
c2 := exec.Command("wc", "-l")
c2.Stdin, _ = c1.StdoutPipe()
c2.Stdout = os.Stdout
c2.Stderr = os.Stderr
c2.Start()
c1.Run()
c2.Wait()

}

func run3() {

c1 := exec.Command("ps", "-eaf")
c2 := exec.Command("grep", `"nginx: master"`)
c3 := exec.Command("grep", "-v", `"grep"`)
c4 := exec.Command("awk", `'{print $2}'`)
c2.Stdin, _ = c1.StdoutPipe()
c3.Stdin, _ = c2.StdoutPipe()
c4.Stdin, _ = c3.StdoutPipe()

c4.Stdout = os.Stdout
c4.Stderr = os.Stderr

c4.Start()
c3.Start()
c2.Start()
c1.Run()
c4.Wait()

}

func run4() {

cmd := exec.Command("/bin/sh", "-c", `ps -eaf|grep "nginx: master"|grep -v "grep"|awk '{print $2}'`)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Start()
cmd.Run()
cmd.Wait()

}

`