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

qinerg · · 8890 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

有一个需求是用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()
}



有疑问加站长微信联系(非本文作者)

本文来自:开源中国博客

感谢作者:qinerg

查看原文:让go语言调用外部程序时支持管道符

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

8890 次点击  ∙  3 赞  
加入收藏 微博
2 回复  |  直到 2018-04-26 11:31:44
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传