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

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

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

最近在一个 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 命令的场合。


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

查看所有标签

猜你喜欢:

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

Learn Python 3 the Hard Way

Learn Python 3 the Hard Way

Zed A. Shaw / Addison / 2017-7-7 / USD 30.74

You Will Learn Python 3! Zed Shaw has perfected the world’s best system for learning Python 3. Follow it and you will succeed—just like the millions of beginners Zed has taught to date! You bring t......一起来看看 《Learn Python 3 the Hard Way》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

MD5 加密
MD5 加密

MD5 加密工具