一个让go的exec支持管道的小窍门

栏目: Go · 发布时间: 7年前

内容简介:最近在一个由于是第一次用运行的时候发现这段代码是不能正确的工作的,经过在网上一通搜索后,发现网上给出的方案大致都是这个样子的:

最近在一个 golang 开发的项目中需要用 exec 库调用外部 shell 命令,这个命令中用到了管道( pipline )。

由于是第一次用 exec 库,我想当然的把代码写成了这个样子:

package main

import "fmt"
import "os/exec"

func main() {
    cmdStr := fmt.Sprintf("ls -l %s | head -n %d", ".", 10)
    cmd := exec.Command(cmdStr)
    if out, err := cmd.CombinedOutput(); err != nil {
        fmt.Errorf("Error: %v\n", err)
    } else {
        fmt.Printf("Success: %s\n%s\n", cmdStr, out)
    }
}

运行的时候发现这段代码是不能正确的工作的,经过在网上一通搜索后,发现网上给出的方案大致都是这个样子的: https://stackoverflow.com/questions/10781516/how-to-pipe-several-commands-in-go 。这种方案确实是解决了问题,但是看起来却十分的复杂,我只是想调用一句 shell 命令而已,却要多写上十几行的 go 代码。

有没有更简单的方法呢?既然 go 自身处理不了,是否可以用 go 之外的 工具 来解决呢?

然后就有了这个曲线救国的方案, exec 不再直接执行这个带有管道的命令,而是执行 sh 命令,然后我们的带有管道的 shell 命令作为参数传给 sh 来运行,类似于:

sh -c "ls -l . | head -n 10"

至此,问题迎刃而解,比网上找到的方案简单了很多。落实到 go 代码大概就是下面的样子:

package main

import "fmt"
import "os/exec"

func main() {
    cmdStr := fmt.Sprintf("ls -l %s | head -n %d", ".", 10)
    cmd := exec.Command("sh", "-c", cmdStr)
    if out, err := cmd.CombinedOutput(); err != nil {
        fmt.Errorf("Error: %v\n", err)
    } else {
        fmt.Printf("Success: %s\n%s\n", cmdStr, out)
    }
}

其实原则上,不局限于本题中管道的情形,这个方案还可以用在更多的需要调用复杂的 shell 命令的场合。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

大数据预测

大数据预测

【美】埃里克·西格尔 / 周昕 / 中信出版社 / 2014-3 / 58.00

360公司董事长周鸿祎、《罗辑思维》主讲人罗振宇郑重推荐 2020年的一天,在你驱车前往公司的路上,导航系统通过预测交通流量,会自动帮你选择一条最合适的交通路线;车内推荐系统会根据你的饮食习惯预测你可能会喜欢吃什么,并推荐沿途的早餐店;你的电子社交助理已经为你自动选择了你可能感兴趣的社交网信息;当车内系统预测到你驾车有些分心时,座椅会自动震动进行提醒…… 以上这些情景不是科幻大片独有的......一起来看看 《大数据预测》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具