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

如何将可执行二进制文件的输出写入内存而不是磁盘

如何将可执行二进制文件的输出写入内存而不是磁盘

Go
慕桂英3389331 2023-02-06 14:45:15
我得到了一个像下面这样工作的二进制文件:> ./my_bin raw.avi output_file.avioutput_file.avi是我想要的,当作业成功时,终端会打印一些详细信息,例如:版权所有 2022 Company Inc... 成功。我想在我的代码中运行这个命令并将其重定向output_file.avi到某个字节数组,这样我就不必从磁盘读取它并删除它。我的方法类似于下面的 Golang 代码片段:func wrongOne(stdin []byte) ([]byte, error) {    inBuf := bytes.NewBuffer(stdin)    outBuf := bytes.NewBuffer(nil)    cmd := exec.Command("./my_bin", "/dev/stdin", "/dev/stdout")    cmd.Stdin = inBuf    cmd.Stdout = outBuf    err := cmd.Run()    if err != nil {        return nil, err    }    return outBuf.Bytes(), nil // wrong}但是,返回的字节数组比下面的方法长,这会导致 MD5 检查失败。func correctOne(stdin []byte) ([]byte, error) {    inBuf := bytes.NewBuffer(stdin)    cmd := exec.Command("./my_bin", "/dev/stdin", "output_file")    cmd.Stdin = inBuf    err := cmd.Run()    if err != nil {        return nil, err    }    return os.ReadFile("output_file")}该wrongOne功能可以修改为以下代码是正确的:func modifiedWrongOne(stdin []byte) ([]byte, error) {    inBuf := bytes.NewBuffer(stdin)    outBuf := bytes.NewBuffer(nil)    cmd := exec.Command("./my_bin", "/dev/stdin", "/dev/stdout")    cmd.Stdin = inBuf    cmd.Stdout = outBuf    err := cmd.Run()    if err != nil {        return nil, err    }    correct, _ := correctOne(stdin)    return outBuf.Bytes()[:len(correct)], nil // diff}我假设输出详细信息包含在 中,/dev/stdout因此该wrongOne函数不起作用。IE,wrongOne= 的输出+ correctOne[]byte{"Copyright 2022 Company Inc... Success."}有没有什么解决方案可以output_file.avi在不将其保存为文件并从磁盘读取的情况下获取管道?谢谢!
查看完整描述

2 回答

?
HUH函数

TA贡献1836条经验 获得超4个赞

该命令将版权声明写入标准输出。为避免将版权声明与输出文件混在一起,请使用 /dev/stdout 以外的文件作为输出文件。

下面的函数使用Cmd.ExtraFiles管道连接到子进程中的 fd 3。该函数将数据从管道复制到字节缓冲区,并将这些字节返回给调用者。

func otherOne(stdin []byte) ([]byte, error) {

    r, w, err := os.Pipe()

    if err != nil {

        return nil, err

    }

    defer r.Close()

    defer w.Close()


    cmd := exec.Command("./my_bin", "/dev/stdin", "/dev/fd/3")

    cmd.Stdin = bytes.NewReader(stdin)

    cmd.ExtraFiles = []*os.File{w} // The first file is fd 3.

    if err := cmd.Start(); err != nil {

        return nil, err

    }

    w.Close()

    var outbuf bytes.Buffer

    if _, err := io.Copy(&outbuf, r); err != nil {

        return nil, err

    }

    if err := cmd.Wait(); err != nil {

        return nil, err

    }

    return outbuf.Bytes(), nil

}


查看完整回答
反对 回复 2023-02-06
?
侃侃无极

TA贡献2051条经验 获得超10个赞

几个月后,我想出了另一种方法来解决这个问题。基本思想与Cerise类似,即/dev/fd/3用于重定向输出文件。之后,我们分别重定向/dev/fd/3到/dev/stdout, verbose log 到/dev/stderr by 3>&1, 1>&2。添加了一个额外gen.sh的。这是解决方案:


#gen.sh

./mybin /dev/stdin /dev/fd/3 3>&1 1>&2

// gen.go

func gen(stdin []byte) ([]byte, error) {

    inBuf := bytes.NewBuffer(stdin)

    outBuf := bytes.NewBuffer(nil)

    cmd := exec.Command("./gen.sh")

    cmd.Stdin = inBuf

    cmd.Stdout = outBuf

    cmd.Stderr = os.Stderr

    err := cmd.Run()

    if err != nil {

        return nil, err

    }

    return outBuf.Bytes(), nil

}


查看完整回答
反对 回复 2023-02-06
  • 2 回答
  • 0 关注
  • 120 浏览
慕课专栏
更多

添加回答

举报

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