为了账号安全,请及时绑定邮箱和手机立即绑定

go exec with <(..) 参数

go exec with <(..) 参数

Go
尚方宝剑之说 2021-09-21 16:17:46
我正在尝试使用 exec 获得等效项diff <(echo "foo") <(echo "bar")它产生:1c1< foo---> bar但是当我尝试:cmd := exec.Command("diff", "<(echo foo)", "<(echo bar)")输出是:exit status 2diff: <(echo foo): No such file or directorydiff: <(echo bar): No such file or directory
查看完整描述

1 回答

?
RISEBY

TA贡献1856条经验 获得超5个赞

FUZxxl 的回答很简单,但是需要使用 bash。Bash 并不是真正的跨平台,并且作为解释器对代码注入是开放的。我将首先描述一种用 Go 复制这个的方法,然后描述 git 使用的答案。


<(echo foo) 在 bash 中做了两件事。首先,它创建一个文件描述符以传递给被调用的命令。它做的第二件事是将 /dev/fd/n 作为参数传递。为了确认,请尝试:


echo <(echo foo) <(echo bar)

Echo 忽略 fds 并仅将文件描述符打印为字符串。


下面的 Go 代码会做类似的事情:


package main


import (

    "io"

    "log"

    "os"

    "os/exec"

    "strings"

)


func main() {

    cmd := exec.Command("diff", "/dev/fd/3", "/dev/fd/4")


    foo, err := readerFile(strings.NewReader("foo\n"))

    if err != nil {

        log.Fatal(err)

    }

    defer foo.Close()


    bar, err := readerFile(strings.NewReader("bar\n"))

    if err != nil {

        log.Fatal(err)

    }

    defer bar.Close()


    cmd.ExtraFiles = []*os.File{foo, bar}


    cmd.Stdout = os.Stdout

    cmd.Stderr = os.Stderr

    err = cmd.Run()

    if err != nil {

        log.Fatal(err)

    }

}


func readerFile(r io.Reader) (*os.File, error) {

    reader, writer, err := os.Pipe()


    if err != nil {

        return nil, err

    }


    go func() {

        io.Copy(writer, r)

        writer.Close()

    }()


    return reader, nil

}

显然,这仅适用于类 Unix 系统,因此不是非常跨平台。但是它不受代码注入的影响。


GIT的方式

Git 只是制作临时文件,然后比较它们。这是极其跨平台的并且不受注射影响。只需使用ioutil.TempFile创建这两个文件,然后运行exec.Command("diff", file1, file2).


查看完整回答
反对 回复 2021-09-21
  • 1 回答
  • 0 关注
  • 233 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信